这一次,彻底弄懂 Promise
关注“前端学苑” ,坚持每天进步一点点
「~彻底弄懂 Promise 原理~」
Promise的出现是为了更好地解决JavaScript中异步编程的问题,Promise可以让我们通过链式调用的方法去解决回调嵌套的问题,使我们的代码更容易理解和维护,而且Promise还增加了许多有用的特性,让我们处理异步编程得心应手。
回调方法(callback)
简单说回调方法就是将一个方法func2作为参数传入另一个方法func1中,当func1执行到某一步或者满足某种条件的时候才执行传入的参数func2。
请求1(function(请求结果1){
请求2(function(请求结果2){
处理请求结果2
})
})
某些情况下,回调嵌套很多时,代码就会非常繁琐,会给我们的编程带来很多的麻烦,这种情况俗称——回调地狱。
重要说明:
优点:解决了同步的问题(只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。)
缺点:回调地狱,不能用 try catch 捕获错误,不能 return。
回调地狱的根本问题:
1)缺乏顺序性:回调地狱导致的调试困难,和大脑的思维方式不符。
2)嵌套函数存在耦合性,一旦有所改动,就会牵一发而动全身,即(控制反转)。
3)嵌套函数过多的多,很难处理错误。
Promise
Promise就是为了解决callback的问题而产生的。Promise 是用来管理异步编程的,它本身不是异步的。
Promise 采用了回调函数延迟绑定技术,在执行 resolve 函数的时候,回调函数还没有绑定,那么只能推迟回调函数的执行。
let p1 = new Promise((resolve,reject)=>{
console.log(1);
resolve('浪里行舟')
console.log(2)
})
// then:设置成功或者失败后处理的方法
p1.then(result=>{
//p1延迟绑定回调函数
console.log('成功 '+result)
},reason=>{
console.log('失败 '+reason)
})console.log(3)
结果:// 1// 2// 3// 成功 浪里行舟
new Promise的时候先执行executor函数,打印出 1、2,Promise在执行resolve时,触发微任务,还是继续往下执行同步任务, 执行p1.then时,存储起来两个函数(此时这两个函数还没有执行),然后打印出3,此时同步任务执行完成,最后执行刚刚那个微任务,从而执行.then中成功的方法。
1、Promise的基本用法
Promise是异步编程的一种解决方案,它有三种状态,分别是pending-进行中、resolved-已完成、rejected-已失败。
new Promise(
function(resolve,reject){
// 一段耗时很长的异步操作
resolve(); // 数据处理完成
reject(); // 数据处理出错
}
)
.then(function A() {
// 成功,下一步
}, function B() {
// 失败,做相应处理
});
.then()方法使Promise原型链上的方法,它包含两个参数方法,分别是已成功resolved的回调和已失败rejected的回调。
.catch()的作用是捕获Promise的错误,与then()的rejected回调作用几乎一致。
2、Promise链式调用
把多个Promise连接到一起来表示一系列异步骤。可以实现的关键两个Promise 固有行为特性:
1)每次你对Promise调用then,它都会创建并返回一个新的Promise,我们可以将其链接起来;
2)不管从then调用的完成回调(第一个参数)返回的值是什么,它都会被自动设置为被链接Promise(第一点中的)的完成。
new Promise(请求1)
.then(请求2(请求结果1))
.then(请求3(请求结果2))
.then(请求4(请求结果3))
.then(请求5(请求结果4))
.catch(处理异常(异常信息))
3、Promise的三个缺点
1)无法取消Promise,一旦新建它就会立即执行,无法中途取消。
2)如果不设置回调函数,Promise内部抛出的错误,不会反映到外部。
3)当处于pending状态时,无法得知目前进展到哪一个阶段,是刚刚开始还是即将完成。
4、Promise 的常用 API 如下:
Promise.resolve(value) 类方法,该方法返回一个以 value 值解析后的 Promise 对象
1) 如果这个值是个 thenable(即带有 then 方法),返回的 Promise 对象会“跟随”这个 thenable 的对象,采用它的最终状态(指 resolved/rejected/pending/settled)
2) 如果传入的 value 本身就是 Promise 对象,则该对象作为 Promise.resolve 方法的返回值返回。
3) 其他情况以该值为成功状态返回一个 Promise 对象。
Promise.reject 类方法,且与 resolve 唯一的不同是,返回的 promise 对象的状态为 rejected。
Promise.prototype.then 实例方法,为 Promise 注册回调函数,函数形式:fn(vlaue){},value 是上一个任务的返回结果,then 中的函数一定要 return 一个结果或者一个新的 Promise 对象,才可以让之后的then 回调接收。
Promise.prototype.catch
实例方法,捕获异常,函数形式:fn(err){}, err 是 catch 注册 之前的回调抛出的异常信息。
Promise.race
类方法,多个 Promise 任务同时执行,返回最先执行结束的 Promise 任务的结果,不管这个 Promise 结果是成功还是失败。。
Promise.all
类方法,多个 Promise 任务同时执行。
如果全部成功执行,则以数组的方式返回所有 Promise 任务的执行结果。
如果有一个 Promise 任务 rejected (数据处理出错),则只返回 rejected 任务的结果。
async、await
async、await很好的解决将异步强行转换为同步处理。async/await的实现是基于 Promise的,简单而言就是async 函数就是返回Promise对象,是generator的语法糖。是ES7中新增的异步编程方法。
async、await 是异步的终极解决方案
1)语法简洁,更像是同步代码,也更符合普通的阅读习惯;
2)改进JS中异步操作串行执行的代码组织方式,减少callback的嵌套;
3)Promise中不能自定义使用try/catch进行错误捕获,但是在Async/await中可以像处理同步代码处理错误。
规则:
1)async和await是配对使用的,await存在于async的内部。否则会报错。
2)await表示在这里等待一个promise返回,再接下来执行。
错误捕获:如果是reject状态,可以用try-catch捕捉。
重要说明:
优点:代码清晰,不用像 Promise 写一大堆 then 链,处理了回调地狱的问题
缺点:await 将异步代码改造成同步代码,如果多个异步操作没有依赖性而使用 await 会导致性能上的降低。
觉得本文对你有帮助?请分享给更多人
关注「前端学苑」加星标,提升前端技能