参考: https://juejin.cn/post/7047492676190634021#comment
https://juejin.cn/post/7102708871763853348
1、前置知识:
(1)promise的基本知识
- 作用:异步处理;解决“回调地狱”,提高可读性
- 三种状态:pending、resolved(也叫fulfilled)、rejected(后两种状态只能从pending转换过来,不存在resolved、rejected互转)
实例方法:
- then:会返回一个promise对象;参数是两个回调函数,resolved、rejected状态对应的执行函数
- catch:相当于then中的第二个函数
- all:一个promise对象数组,全部执行成功则返回一个状态为resolved的promise对象;否则rejected
- race:一个promise对象数组,返回第一个完成的promise对象,无论是resolved还是rejected
(2)原型
在MyPromise类的原型上写方法,实例p可以继承
2、Promise实现
(1)构造函数
function MyPromise(executor) {
this.status = 'pending'
this.result = null
// 箭头函数不会改变this指向,this仍然指向当前的promise对象,而不是指向resolve函数
const resolve = (data) => {
if(this.status !== 'pending')
return
this.status = 'resolved'
this.result = data
// 队列思想,先进先出;
// 1、执行then方法时,为pending状态的每个promise对象保存一对回调函数;
// 2、等到状态变为resolved时,从队列中取出暂存的回调函数,顺序调用
while(this.onResolvedCallbacks.length > 0) {
this.onResolvedCallbacks.shift()() // 调用
this.onRejectedCallbacks.shift()
}
}
const reject = (data) => {
if(this.status !== 'pending')
return
this.status = 'rejected'
this.result = data
while(this.onRejectedCallbacks.length > 0) {
this.onResolvedCallbacks.shift()
this.onRejectedCallbacks.shift()() // 调用
}
}
// 把写好的resolve、reject作为MyPromise构造函数的两个参数
executor(resolve, reject)
}
关于executor(resolve, reject)的理解:
① 先看promise对象的创建形式:
// 箭头函数就对应了上面代码中的executor
let p1 = new MyPromise((resolve, rejct)=>{
// 函数体
// 需要显式调用resolve、reject函数,修改promise状态
resolve('ok')
})
② resolve、reject
这两个函数,是我们在MyPromise中事先写好的,使用executor(resolve, reject),分配给MyPromise构造函数的两个对应参数
改成以下形式也是一样的效果,因为这里是形参:
let p1 = new MyPromise((success, failed)=>{
success(‘ok’)
})
然后,在函数体中调用时,才会执行相应的函数代码
③ executor的作用
将实例的参数名(回调函数名)跟MyPromise类中的resolve、reject对应起来
(2)then、catch方法
① then返回的是一个promise对象(支持链式调用)
MyPromise.prototype.then = function (onResolved, onRejected) {
// 如果传入参数不是函数,为其初始化为空函数
onResolved =