这篇文章根据A+规范和Promise官网描述实现的Promise,看完对Promise的理解增加90%
Promise的特性无非就这几种
Promise的状态是不可逆的Promise通过调用resolve和reject方法修改当前Promise的状态then方法是异步执行的,是微任务,通过传入回调函数得到成功或失败后的结果then方法不传入回调函数会有穿透效果,结果会传递到下一个then方法then方法的返回值是立即成功的Promise对象,除非then方法内的回调函数发生报错then方法是可以链式调用的,每个then得到的结果就是上一个then方法的返回值catch方法在Promise状态为失败时执行,传入回调函数得到失败的结果catch方法返回值是立即成功的Promise对象,除非catch方法内的回调函数发生报错finally方法无论当前Promise状态成功还是失败都会执行,并且返回值为与当前Promise状态一致的Promise对象Promise.all()方法将多个多个Promise实例,包装成一个新的Promise实例,该方法接受一个由Promise对象组成的数组作为参数(Promise.all()方法的参数可以不是数组,但必须具有Iterator接口,且返回的每个成员都是Promise实例),注意参数中只要有一个实例触发catch方法,都会触发Promise.all()方法返回的新的实例的catch方法,如果参数中的某个实例本身调用了catch方法,将不会触发Promise.all()方法返回的新实例的catch方法Promise.race()方法的参数与Promise.all方法一样,参数中的实例只要有一个率先改变状态就会将该实例的状态传给Promise.race()方法,并将返回值作为Promise.race()方法产生的Promise实例的返回值Promise.resolve()方法返回一个立即成功的Promise对象,并且传入的参数分3种情况:Promise自己的实例对象满足A+规范的实例对象传入值三种情况的结果都不一样Promise.reject()方法相对简单,返回值是立即失败的Promise对象,传入的参数是什么返回的Promise对象的值就是什么
状态不可逆
在我们调用resolve方法或者reject方法时,只有当Promise的状态为pending时才可以修改为成功或者失败,先调用了resolve后调用reject,那么reject方法是没有效果的,比如:
new Promise((resolve,reject) => {
resolve('成功')
reject('失败')
})
这段代码最后的结果返回的是状态为fulfilled值为成功的Promise对象,reject方法执行了但是内部不会做任何行为
异步调用resolve和reject方法
我们使用Promise更多情况是发送AJAX请求,AJAX是一个异步任务,所以我们在发送请求成功后调用resolve方法时为什么会等待异步任务完成后,还能获取到数据呢? 这里使用定时器模拟请求,比如:
new Promise((resolve,reject) => {
setTimeout(() => {
resolve('成功')
})
})
因为我们传入的函数是同步执行的,所以修改不到状态,那么Promise内部通过把回调函数中所有的参数保存到对象中推到一个队列里面,当异步任务完成时修改了状态,就从队列中把所需的参数拿出来执行
then方法
then方法最关键的地方就在于他返回的是一个新的Promise对象,才足以实现这么多功能
then内的回调函数是微任务
then方法中是异步执行的,有3种方法,首先判断你所处的是什么环境,使用不同的方法
- 首先判断有没有
process对象,如果有则调用precess.nextTick方法实现微任务 - 判断有没有
MutationObserver这个构造函数,如果有就使用MutationObserver实现微任务 - 都没有那只能使用
setTimeout来实现异步,setTimeout内的回调会添加到延时队列,执行优先级会低于微任务
then方法的穿透效果
执行then时会去判断传入的回调函数是否为function类型,如果不为function那么会返回一个新的Promise对象,调用resolve方法把当前回调的结果传进去,那么下一个then方法就可以接收到上一个then的结果了
链式调用
then方法返回的是一个Promise对象,那么我们就可以调用他的原型方法了,返回Promise对象是链式调用的关键
resolve静态方法
我们传入的参数分三种情况
- 由
Promise实例化的对象
返回值为Promise对象,调用resolve方法,把传入这个对象,作为参数传入,调用then方法时得到的就是传入的Promise对象,举个例子:
const p = new Promise((resolve,reject) => {
resolve('成功')
})
console.log(Promise.resolve(p) === p) // true
- 传入一个满足A+规范的对象
不管你是函数,构造函数,还是对象,只要你满足了then方法就是满足了A+规范,Promise内容判断你符合了A+规范时,会调用你自身的then方法,返回的结果取决于then方法
- 传入普通值
返回的就是一个成功状态的Promise,结果就为传入的参数
await async 跟 Promise 的区别
- 都是用来处理异步代码请求的
- Promise是es6出的,async await是es7出的
- async await是基于Promise实现的,都是非阻塞性的
- Promise是通过then()和catch()处理结果和捕获异常,可以链式调用,还是会出现回调地狱的情况
- async await是通过try catch捕获异常
- 最大的区别就是async await代码看起来跟同步一样,当遇到await就会立即返回结果