最近一直很困惑Promise的许多细节点,故理了一下思绪,手撕Promise源码,有注释,已测试通过
/*
尽可能还原 Promise 中的每一个 API
*/
const PENDING='pending'; //状态:等待中
const FULFILLED='fulfilled'; //状态:成功
const REJECTED='rejected'; //状态:失败
class MyPromise {
constructor(executor) { //增加执行器并且立即执行
try{
executor(this.resolve,this.reject)
}catch (e) {
this.reject(e) //捕捉执行器错误,并且在then里面的错误错误回调函数抛出
}
}
status=PENDING; //状态默认等待中
value=undefined; //resolve传递的值,保存到类上
reason=undefined; //reject传递的值,保存到类上
successCallback=[]; //成功回调函数
failCallback=[]; //失败回调函数
resolve=value=>{
if(this.status!==PENDING) return //状态一旦改变,不是PENDING则不可再更改
this.status=FULFILLED;
this.value=value; //状态成功的VALUE暂时存储
while (this.successCallback.length){
this.successCallback.shift()(); //循环调用数组内的方法
}
}
reject=reason=>{
if(this.status!==PENDING) return //状态一旦改变,不是PENDING则不可再更改
this.status=REJECTED;
this.reason=reason; //状态失败的REASON暂时存储
while (this.failCallback.length) this.failCallback.shift()(); //循环调用数组内的方法
}
then(successCallback,failCallback){
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => {throw reason}
let promise = new MyPromise((resolve,reject)=>{
if(this.status===FULFILLED){
setTimeout(()=>{
promiseFunc({fn:successCallback,promise,resolve,reject,value:this.value})
},0);
}else if(this.status===REJECTED){
setTimeout(()=>{
promiseFunc({fn:failCallback,promise,resolve,reject,value:this.reason})
},0);
}else{
//异步函数时状态依然为pending时,把成功回调函数和失败回调函数暂时存储
this.successCallback.push(()=>{
setTimeout(()=>{
promiseFunc({fn:successCallback,promise,resolve,reject,value:this.value})
},0);
});
this.failCallback.push(()=>{
setTimeout(()=>{
promiseFunc({fn:failCallback,promise,resolve,reject,value:this.reason})
},0);
});
}
});
return promise; //then方法最后返回MyPromise实例
}
catch(failCallback){
return this.then(undefined,failCallback);
}
finally(callback){
//通过this.then方法调用callback,无论状态是否成功
return this.then((value)=>{ //finally方法后面可以调用then方法,故返回MyPromise对象
return MyPromise.resolve(callback()).then(()=>value) //等待callback调用完毕才返回成功或者失败后的值
},(reason)=>{
return MyPromise.resolve(callback()).then(()=>{throw reason})
})
}
static all(arr){ //all方法最终返回promise对象,后面可以调用then
const promise2=new MyPromise((resolve,reject)=>{
let result=[];
let index=0;
const addResult=(key,value)=>{
result[key]=value; //不可用result.push方法,顺序会乱
index++
if(index===arr.length){
resolve(result) //数组内元素执行完毕才传到then里面
}
}
for(let i=0;i<arr.length;i++){
let current=arr[i];
if(current instanceof MyPromise){
//是MyPromise对象则通过.then拿到value然后丢到result里面
current.then((v)=>{addResult(i,v)},(r)=>{reject(r)});
}else{
addResult(i,current) //不是MyPromise对象直接丢到result里面
}
}
});
return promise2;
}
static resolve(value){
if(value instanceof MyPromise) return value; //普通数值直接返回
//MyPromise对象直接返回新的MyPromise对象,并且把value传给then方法里面的成功回调函数
return new MyPromise((resolve)=>{
resolve(value);
})
}
}
//then方法里面的promise对象立即执行的部分
const promiseFunc=({fn,promise,resolve,reject,value})=>{
try{
const x=fn(value) //调用resolve函数之后的值塞入成功回调函数内
resolvePromise(promise,x,resolve,reject)
}catch (e) {
reject(e); //捕捉成功回调函数错误,并且在下一个then里面的错误回调函数抛出
}
}
const resolvePromise=(promise,x,resolve,reject)=>{
if(promise===x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
//x可以是在上一个then里面成功回调函数的返回值,也可以是失败回调函数的返回值
if(x instanceof MyPromise){
x.then(resolve,reject)
}else{
resolve(x)
}
}
module.exports=MyPromise;