什么是 Promise?
ES6中新增一个内置的类,Promise是一种承诺/约定模式, 基于这种模式可以有效的处理异步编程,可以解决传统的回调地狱问题
什么是回调地狱,它的缺点又是什么?
- 回调地狱:在传统实现异步操作,并且是串行的模式下,基本上都是回调函数嵌套回调函数,实现"回调地狱"的问题
- 弊端:可维护性差、可读性差、可复用性差、代码量大,并且只能在回调函数中处理异常
解决回调地狱的方式有哪些?
- Promise
- Promise.all
- async/await
Promise 的三大概念
- executor 函数
-
new Promise 的时候会立即执行 executor 函数
-
在 executor 函数中管理了一个异步编程代码(同步代码也是OK的),此时 Promise 状态是 pending;
-
在我们异步操作成功或者失败的时候,通过执行 resolve 或者 reject 函数,可以有效的把实例改成成功状态或者失败状态,也就是从 pending 变为 fulfilled(成功)/rejected(失败);
-
如果代码报错的情况下,也是把状态改为失败;
-
- 实例
-
每一个 Promise 实例都具备[[PromiseState]]和[[PromiseResult]]方法
-
[[PromiseState]] 是 promise 状态:pending、fulfilled/resolve、rejected 三种状态
-
[[PromiseResult]] 是 promise 值:默认是 undefined,一般存储成功的结果或者失败的原因。
-
- then(): 用来管控成功或者失败的操作
-
执行 .then 方法返回一个全新的 promise 实例
-
实例可以调用 .then(),它会存放两个方法:result 和 reason (都是函数)
-
当实例的状态修改为 fulfilled 的时候,通知传递的第一个函数(result)执行,result 就是 [[PromiseResult]] 的值
-
当实例的状态修改为 rejected 的时候,通知传递的第二个函数(reason)执行,reason 就是 [[PromiseResult]] 的值
-
-
不论是否基于 THEN 注入了方法,执行 resolve/reject 的时候,修改状态和值是同步的会立即处理
-
但是,通知对应注入方法执行的这个任务是异步操作的,不会立即处理,只是把它排在等待任务队列中,当其他事情处理完,再次返回去,通知对应注入的方法执行
-
then(onfulfilled, onrejected): 执行 then 方法只是把 onfulfilled/onrejected 函数保存起来了(这个保存的操作是同步的)
-
但是此时函数还没有执行,当 promise 状态变为成功或者失败的时候,才会去触发执行对应的函数
-
所以,then 方法是一个异步的微任务
-
.then() 分为两种情况执行
- 当前实例的状态已经是成功或者失败,此时创建一个异步的微任务,等待同步业务结束,根据成功还是失败,来决定执行哪个方法
- 如果此时的状态还是 pending,则直接把方法存储起来即可,没有创建异步的微任务
- 当执行 resolve/reject 的时候,才会去创建一个异步的微任务,等待同步的结束后根据状态执行基于.then 动态存储的函数
Promise 如何管控异步编程的?
-
new Promise 的时候创建一个 promise 实例,此时在 executor 函数中管理一套异步的代码
-
后期等异步操作成功或者失败的时候,执行 resolve/reject,以此来控制 promise 实例的状态和结果
-
根据状态和结果,就可以控制基于 .then 注入的两个方法中的哪一个去执行了
let p1 = new Promise(function (resolve, reject) {
setTimeout(function(){
resolve('OK');
}, 1000)
});
p1.then(result=>{
console.log('成功', result)
}, reason=>{
console.log('失败', reason)
})
});
Promise 实例状态和值的分析
- 第一种情况:new Promise 出来的实例
-
resolve 和 reject 的执行控制其状态 [[PromiseState]] 以及值 [[PromsieResult]]
-
executor 函数执行失败,控制其状态 [[PromiseState]] 为:rejected 以及值 [[PromsieResult]] 为报错信息
-
- 第二种情况:通过执行 then 返回的新实例
-
then 注入的两个方法,不论哪个方法执行,只要执行不报错,新实例的状态就是 fulfilled;只要执行报错,新实例的状态就是 rejected,并且新实例的 [[PromiseResult]] 是执行 then 方法返回的值
-
如果返回的值是一个新的 promise 实例,则新的 promise 实例最后的成功或者失败,直接决定 then 返回的实例的成功和失败
-
在 .then 注入方法的时候,如果其中某个方法没有传递,则会顺延到下一个 then 中具备相同状态需要执行的函数上
-
在多个 THEN 链下,其余的 THEN 方法基本都存放的是成功处理的事情,最后一个 THEN 存放失败的,这样不论是第一次或者其中某一次,导致 promise 实例状态是失败的,都会顺延到最后一个失败的处理函数上进行处理...
-
then(null, reason=>{...})
用 catch(reason=>{...}) 来代替
同时处理多个 Promise 实例的方法
- Promise.all:等待所有的 promise 实例都成功,整体返回的状态才是成功,只要有一个失败的,整体状态就是失败
- Promise.race:看多个实例谁先处理完,先处理完成的状态不论是失败还是成功,就是最后整体的状态
Promise 常用的属性有哪些?
Promise 作为对象中的属性
- Promise.all
- Promise.race
- Promise.resolve()
- Promise.reject()
Promise 作为类的两个内置属性
- [[PromiseState]] promise 状态
- pending:准备状态
- fulfilled(旧版本浏览器)/resolved(新版本浏览器):成功状态(已兑现)
- rejected:失败状态(已拒绝)
- 但是一旦状态从 pending 改变为 fulfilled 或者是 rejected, 都无法再次改变其状态
- [[PromiseResult]] promise 值
- 默认是 undefined,一般存储成功的结果或者失败的原因
Promise 原型上的方法
- then
- catch
- finally