分析一下实现Promise需要哪些逻辑
- Promise有三种状态,pending(进行中)、fulfilled(已完成)、reject(已失败),外界无法改变其状态,且一旦状态改变就不会再变了
- 实例化一个 Promise 需要传入一个 executor 函数 ,业务代码在 executor 函数中执行,另外 executor 函数接收两个参数 resolve 和 reject。resolve 和 reject 是 Promise 构造函数的内置函数
new Promise((resolve,reject)=>{
// do something
})
- 在 executor 函数中业务代码执行成功了,调用 resolve 函数,把 Promise 的状态变为已成功,另外通过参数把业务代码的执行成功的结果传递到 Promise 中
- 在 executor 函数中业务代码执行失败了,调用 reject 函数,把 Promise 的状态变为已失败,另外通过参数把业务代码的执行失败的原因传递到 Promise 中
- 实例方法 then 的第一个参数是业务代码执行成功的回调函数,第二个参数是业务代码执行失败的回调函数,当业务代码执行完毕后,会根据执行结果调用对应的回调函数,且这些回调函数接收业务代码的执行结果作为参数
- then方法可以链式调用,具有穿透性
- 实例方法 catch 来添加业务代码执行失败的回调函数
那么下面就一一来实现 Promise 的功能
初步搭建
根据分析,首先我们需要完成这些功能:
-
Promise 构造函数接收 executor 函数作为参数,且在其中执行 executor 函数
-
Promise 构造函数中有 resolve 和 reject 内置方法,并作为参数传递给 executor 函数
-
设置个实例属性 status 来存储状态
-
内置函数 resolve 可以把状态变为已成功,内置函数 reject 可以把状态变为已失败,且一旦状态改变就不会再变
// 这里使用了Symbol是为了防止外界其他原因改变了状态
const Pending = Symbol('Pending');
const Fulfilled = Symbol('Fulfilled');
const Rejected= Symbol('Rejected');
function Promise(excutor){
// 初始状态为pending
this.status = Pending;
const resolve = () => { // 这里为了this的指向,使用了箭头函数,如果不用箭头函数,需要用变量存一下this
if(this.status === Pending){ // 只有在状态为pending时才可以发生改变
this.status = Fulfilled;
}
};
const reject = () => {
if(this.status === Pending){ // 只有在状态为pending时才可以发生改变
this.status = Rejected;
}
};
excutor(resolve,reject);
}
初步实现then方法
按照上面对 then 实例方法的业务场景的简单分析,在 then 实例方法中调用回调函数时,还要把 executor 函数中业务代码的执行结果作为参数传递进去,那么要新增实例属性来存储业务代码的执行结果。另外执行成功的结果通过内置方法 resolve 的参数传入,其执行失败的原因通过内置方法 reject 的参数传入
因为then方法是实例可调用的,所以then方法是在构造函数原型上的:
// 这里使用了Symbol是为了防止外界其他原因改变了状态
const Pending = Symbol('Pending');
const Fulfilled = Symbol('Fulfilled');
const Rejected= Symbol('Rejected');
function Promise(excutor){
// 初始状态为pending
this.status = Pending;
this.value = undefined;
this.error = undefined;
const resolve = value => { // 这里为了this的指向,使用了箭头函数,如果不用箭头函数,需要用变量存一下this
if(this.status === Pending){ // 只有在状态为pending时才可以发生改变
this.status = Fulfilled;
this.value = value;
}
};
const reject = value => {
if(this.status === Pending){ // 只有在状态为pending时才可以发生改变
this.status = Rejected;
this.error = value;
}
};
excutor(resolve,reject);
};
Promise.prototype.then = function(resolveCallback,rejectCallback){ // 这里为什么不用箭头函数,注意this指向
if(this.status === Fulfilled){
if(resolveCallback && typeof resolveCallback === 'function'){
resolveCallback(this.value);
}
}
if(this.status === Rejected){
if(rejectCallback && typeof rejectCallback === 'function'){
rejectCallback(this.error);
}
}
}
初步实现了then方法,那么我来验证一下ÿ