乐趣区

关于javascript:5K字-由浅入深聊聊Promise实现原理

前言

大家好,我是梁木由,是一个有想头的前端。这几天再回顾基础知识时,对 Promise 有了较为深刻的了解,那明天就来分享下怎么由浅入深的把握 Promise 并且学会手写 Promise

概念

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更正当和更弱小。它由社区最早提出和实现,ES6 将其写进了语言规范,对立了用法,原生提供了 Promise 对象。

所谓Promise,简略说就是一个容器,外面保留着某个将来才会完结的事件(通常是一个异步操作)的后果。从语法上说,Promise 是一个对象,从它能够获取异步操作的音讯。Promise 提供对立的 API,各种异步操作都能够用同样的办法进行解决。

Promise 拉进去单练

那咱们先把 Promise 拉进去练练,看看是什么玩意,在控制台中打印看下

在上图能够看出什么信息呢,那咱们列举下

  • 首先咱们看出在 new Promise 时,须要传入一个回调函数
  • 它是一个类,并且会返回一个 Promise 对象
  • 那还能够看出它有 constructor 构造函数,还有 catchfinallythen 三个办法

那咱们根据上述剖析出的信息,简略实现一下

class CustomPromise {constructor(callBack) { }
  catch() {}
  then() {}
  finally() {}
}
const customPromise = new CustomPromise()
console.log(customPromis)

看下咱们本人简略实现的输入后果

那咱们再写一个 Promise 的惯例用法

const promise = new Promise((resolve, reject) => {console.log("hellow Promise");
});
console.log(promise);

那咱们来看看打印后果,能剖析出什么后果

  • hellow promise 在控制台被输入了,那是不是说咱们传入的回调函数被立刻执行了,那阐明传入的是一个执行器

那再改良一下咱们的 CustomPromise

class CustomPromise {constructor(executor) {executor()
  }
  catch() {}
  then() {}
  finally() {}
}
const customPromise = new CustomPromise((resolve, reject) => {console.log('hellow Promise')
})
console.log(customPromise)

Promise 基本原理与基本特征

那咱们来看看咱们所熟知的 Promise 的基本原理

  • 首先咱们在调用 Promise 时,会返回一个 Promise 对象。
  • 构建 Promise 对象时,须要传入一个 executor 函数,Promise 的次要业务流程都在 executor 函数中执行。
  • 如果运行在 excutor 函数中的业务执行胜利了,会调用 resolve 函数;如果执行失败了,则调用 reject 函数。
  • Promise 的状态不可逆,同时调用 resolve 函数和 reject 函数,默认会采取第一次调用的后果。

联合 Promise/A+ 标准,咱们还能够剖析出哪些基本特征

Promise/A+ 的标准比拟多,在这列出一下外围的标准。Promise/A+ 标准

  • promise 有三个状态:pending,fulfilled,rejected,默认状态是 pending。
  • promise 有一个 value 保留胜利状态的值,有一个 reason 保留失败状态的值,能够是 undefined/thenable/promise。
  • promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled,状态一旦确认,就不会再扭转。
  • promise 必须有一个 then 办法,then 接管两个参数,别离是 promise 胜利的回调 onFulfilled, 和 promise 失败的回调 onRejected。
  • 如果 then 中抛出了异样,那么就会把这个异样作为参数,传递给下一个 then 的失败的回调 onRejected。

CustomPromise,还实现不了基本原理的 3,4 两条,那咱们来依据基本原理与 Promise/A+ 剖析下,还短少什么

  • promise 有三个状态:pending,fulfilled,rejected。
  • executor 执行器调用 reject 与 resolve 两个办法
  • 还须要有保留胜利或失败两个值的变量
  • then 接管两个参数,别离是胜利的回调 onFulfilled, 失败的回调 onRejected

那再来改良下CustomPromise

// 定义三个常量示意状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
​
class CustomPromise {constructor(executor) {executor(this.resolve, this.reject);
  }
  // resolve 和 reject 为什么要用箭头函数?// 如果间接调用的话,一般函数 this 指向的是 window 或者 undefined
  // 用箭头函数就能够让 this 指向以后实例对象
  resolve = (value) => {this.value = value;};
  reject = (value) => {this.reason = value;};
  // 胜利之后的值
  value = undefined;
  // 失败之后的值
  reason = undefined;
​
  then(onFulfilled,onRejected) { }
  catch() {}
  finally() {}
}

那咱们依据 Promise 基本原理看看它原生 Promise 的成果

new Promise(function (resolve, reject) {resolve("胜利");
  reject("失败");
}).then((value) => {console.log(value); // 后果为‘胜利’},
  (err) => {console.log(err);
  }
);
​
new Promise(function (resolve, reject) {reject("失败");
  resolve("胜利");
}).then((value) => {console.log(value);
  },
  (err) => {console.log(err); // 后果为‘失败’}
);

能够看出与基本原理一样的成果,那咱们剖析下如何实现这种成果

  • 须要管制 promise 状态
  • 在 then 办法里要调用胜利或失败的回调函数
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
​
class CustomPromise {constructor(executor) {executor(this.resolve, this.reject);
  }
  // resolve 和 reject 为什么要用箭头函数?// 如果间接调用的话,一般函数 this 指向的是 window 或者 undefined
  // 用箭头函数就能够让 this 指向以后实例对象
  resolve = (value) => {
    // promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled
    if (this.status == PENDING) {
      this.status = FULFILLED;
      this.value = value;
    }
  };
  reject = (err) => {
    // promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled
    if (this.status == PENDING) {
      this.status = REJECTED;
      this.reason = err;
    }
  };
  status = PENDING;
  // 胜利之后的值
  value = undefined;
  // 失败之后的值
  reason = undefined;
​
  then(onFulfilled, onRejected) {
    // 须要判断状态,依据状态抉择解决回调函数
    if (this.status == FULFILLED) {onFulfilled(this.value);
    } else if (this.status == REJECTED) {onRejected(this.reason);
    }
  }
  catch() {}
  finally() {}
}

来测试下CustomPromise

new CustomPromise(function (resolve, reject) {resolve("胜利");
  reject("失败");
}).then((value) => {console.log(value);// 后果为‘胜利’},
  (err) => {console.log(err);
  }
);
​
new CustomPromise(function (resolve, reject) {reject("失败");
  resolve("胜利");
}).then((value) => {console.log(value);
  },
  (err) => {console.log(err);// 后果为‘失败’}
);
​

Promise.then 链式调用

咱们都知到 Primose.then 是能够链式调用的,那咱们先看看原生成果

const promise = new Promise((resolve, reject) => {resolve("start");
});
promise
  .then((res) => {console.log(res);
    return new Promise((resolve, reject) => {setTimeout(() => {resolve("hellow");
     },3000)
    });
  })
  .then((res) => {console.log(res);
    return "promise";
  })
  .then((res) => {console.log(res);
  });

输入后果

start
hellow
promise

那咱们来剖析实现一下

  • 首先.then 是须要返回一个 Promise
  • 下一个.then 须要拿到上一个.then 的返回值
  • 有异步操作的话,后一个回调函数,会期待该 Promise 对象的状态发生变化,在被调用
  • 有异步操作的话,那就是说有工作队列,须要有收集回调函数的队列
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
​
class CustomPromise {constructor(executor) {executor(this.resolve, this.reject);
  }
  // resolve 和 reject 为什么要用箭头函数?// 如果间接调用的话,一般函数 this 指向的是 window 或者 undefined
  // 用箭头函数就能够让 this 指向以后实例对象
  resolve = (value) => {
    // promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled
    if (this.status == PENDING) {
      this.status = FULFILLED;
      this.value = value;
​
      // resolve 外面将所有胜利的回调拿进去执行
      if (this.onResolvedCallbacks.length) {this.onResolvedCallbacks.forEach((fn) => fn());
      }
    }
  };
  reject = (err) => {
    // promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled
    if (this.status == PENDING) {
      this.status = REJECTED;
      this.reason = err;
      // reject 外面将所有失败的回调拿进去执行
      if (this.onFulfilledCallbacks.length) {this.onFulfilledCallbacks.forEach((fn) => fn());
      }
    }
  };
  // 存储胜利回调函数
  onResolvedCallbacks = [];
  // 存储失败回调函数
  onFulfilledCallbacks = [];
​
  status = PENDING;
  // 胜利之后的值
  value = undefined;
  // 失败之后的值
  reason = undefined;
​
  then(onFulfilled, onRejected) {
    // 如果不传,就应用默认函数, 确保是函数类型
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {throw reason;};
​
    const thenCustomPromise = new CustomPromise((resolve, reject) => {const resolveCustomPromise = (callBack, value) => {
        try {const x = callBack(value);
          // 如果相等了,阐明 return 的是本人,抛出类型谬误并返回
          if (resolveCustomPromise === x) {return reject(new TypeError("类型谬误"));
          }
          // 判断 x 是不是 CustomPromise 实例对象
          if (x instanceof CustomPromise) {
            // 执行 x,调用 then 办法,目标是将其状态变为 fulfilled 或者 rejected
            // x.then(value => resolve(value), error => reject(reason))
            // 简化之后
            x.then(resolve, reject);
          } else {
            // 一般值
            resolve(x);
          }
        } catch (error) {reject(error);
        }
      };
      // 须要判断状态,依据状态抉择解决回调函数
      if (this.status == FULFILLED) {resolveCustomPromise(onFulfilled, this.value);
      } else if (this.status == REJECTED) {resolveCustomPromise(onRejected, this.reason);
      } else if (this.status == PENDING) {
        // 当状态为 pending 时, 把 then 回调 push 进 resolve/reject 执行队列, 期待执行
        this.onResolvedCallbacks.push(() =>
          resolveCustomPromise(onFulfilled, this.value)
        );
        this.onFulfilledCallbacks.push(() =>
          resolveCustomPromise(onRejected, this.reason)
        );
      }
    });
    return thenCustomPromise;
  }
  catch() {}
  finally() {}
}
​

来验证下.then 的链式调用

const promise = new CustomPromise((resolve, reject) => {resolve("start");
});
promise
  .then((res) => {console.log(res);
    return new CustomPromise((resolve, reject) => {setTimeout(() => {resolve("hellow");
      }, 1000);
    });
  })
  .then((res) => {console.log(res);
    return "promise";
  })
  .then((res) => {console.log(res);
  });
// 输入后果 start->hellow->promise

Promise.prototype.catch()

是 .then(null, rejection) 或是 .then(undefined, rejection)的别名,用于指定产生谬误时的回调函数

看下原生 promise 成果

const promise = new Promise((resolve, reject) => {resolve("start");
});
promise
  .then((res) => {console.log(res);
    return new Promise((resolve, reject) => {reject("hellow");
    });
  })
  .catch(err => {console.log(err); return 'promise'})
  .then(res => console.log(res))

输入后果

start
hellow
promise

根据上述原生 catch 咱们来剖析下后果

  • 执行.then 的 onRejected 回调函数
  • 并且能够持续链式调用
catch(onFulfilled) {return this.then(null, onFulfilled)
}

那咱们来验证下

const promise = new CustomPromise((resolve, reject) => {resolve("start");
});
promise
  .then((res) => {console.log(res);
    return new CustomPromise((resolve, reject) => {reject("hellow");
    });
  })
  .catch((err) => {console.log(err);
    return "promise";
  })
  .then((res) => console.log(res));
​
// 输入后果
start
hellow
promise

Promise.resolve()

Promise.resolve(value)返回一个解析过的 Promise 对象,用法有一个 value 参数

  • 如果参数是 Promise 实例,那么 Promise.resolve 将不做任何批改、一成不变地返回这个实例。

    • const promise = new Promise((resolve, reject) => {resolve("start");
      });
      ​
      const resolvePromise = Promise.resolve(promise);
      resolvePromise.then((res) => console.log(res)); 
  • 如果参数是 具备 then 办法的对象 Promise.resolve() 办法会将这个对象转为 Promise 对象,而后就立刻执行 thenable 对象的 then() 办法

    • let thenable = {then: function(resolve, reject) {resolve('promise');
        }
      };
      ​
      let p1 = Promise.resolve(thenable);
      p1.then(function (res) {console.log(res);  // promise
  • 如果参数是一个原始值,或者是一个不具备 then() 办法的对象,则 Promise.resolve() 办法返回一个新的 Promise 对象,状态为resolved

    • const p1 = Promise.resolve('promise');
      ​
      p1.then(function (res) {console.log(res)
      });
  • Promise.resolve()办法容许调用时不带参数,间接返回一个 resolved 状态的 Promise 对象

    • const p = Promise.resolve();
      ​
      p.then(function () {// ...

参考资料:[ECMAScript 入门](https://es6.ruanyifeng.com/#d…

CustomPromise 增加动态 resolve 办法

// 动态的 resolve 办法
  static resolve(value) {if (value instanceof CustomPromise) return value;
    return new CustomPromise((resolve) => resolve(value));
  }

Promise.reject()

Promise.reject(reason) 返回一个 Promise 实例,并且携带 reason

const promise = Promise.reject("rejected message")
// 相当于
// const promise2 = new Promsie((resolve, reject) => {//   reject("rejected message")
// })

根据上述例子咱们来剖析下后果

  • 能够看出无论 reason 传入什么内容,都是通过 reject()办法,那是不是能够了解为就是捕捉错误信息

CustomPromise 增加动态 reject 办法

// 动态的 reject 办法
static reject(reason) {return new CustomPromise((resolve, reject) => reject(reason));
}

Promise.prototype.finally()

finally()不接管参数,并且在.then 或.catch 回调函数执行完当前,再执行 finally 中的办法

看下原生 promise 成果

const promise = new Promise((resolve, reject) => {resolve("start");
});
promise
  .then((res) => {console.log(res);
    return new Promise((resolve, reject) => {resolve("hellow");
    });
  })
  .then((res) => {console.log(res);
    return new Promise((resolve, reject) => {resolve("promise");
    });
  })
  .finally(() => {console.log("finally");
    return "is finally";
  })
  .then((res) => console.log(res));
​

输入后果

start
hellow
finally
promise

根据上述原生 finally 咱们来剖析下后果

  • finally 办法和 then 以及 catch 一样,都能够返回一个新的 Promise
  • finally 并不会影响之前返回的 Promise 对象
  • 能够持续链式调用并且获取之前 Promise 的值

CustomPromise 增加动态 finally 办法

finally(callback) {
    return this.then((value) => CustomPromise.resolve(callback()).then(() => value),
      (reason) => CustomPromise.resolve(callback()).then(() => reason)
    );
}

那咱们来验证下

const promise = new CustomPromise((resolve, reject) => {resolve("start");
});
promise
  .then((res) => {console.log(res);
    return new CustomPromise((resolve, reject) => {resolve("hellow");
    });
  })
  .then((res) => {console.log(res);
    return new CustomPromise((resolve, reject) => {resolve("promise");
    });
  })
  .finally(() => {console.log("finally");
    return "is finally";
  })
  .then((res) => console.log(res));
​
// 输入后果
start
hellow
finally
promise

Promise.all()

Promise.all() 办法接管一个 promise 的 iterable 类型 (Array,Map,Set 都属于 ES6 的 iterable 类型) 并返回一个新的 Promise 实例

看下原生 Promise.all() 成果

let p1 = new Promise((resolve, reject) => {resolve("start");
}).then((res) => res);
let p2 = new Promise((resolve, reject) => {resolve("hellow");
}).then((res) => res);
let p3 = new Promise((resolve, reject) => {resolve("promise");
}).then((res) => res);
​
Promise.all([p1, p2, p3])
  .then((res) => console.log("success:", res))
  .catch((err) => console.log("error:", err));
// 输入后果 success:['start', 'hellow', 'promise']
let p1 = new Promise((resolve, reject) => {resolve("start");
}).then((res) => res);
let p2 = new Promise((resolve, reject) => {reject("报错了");
}).then((res) => res);
let p3 = new Promise((resolve, reject) => {reject("报错了 2");
}).then((res) => res);
​
Promise.all([p1, p2, p3])
  .then((res) => console.log("success:", res))
  .catch((err) => console.log("error:", err));
// 输入后果 error: 报错了

那咱们来依据输入后果剖析下

  • 胜利的时候返回的是一个后果数组
  • 失败的时候则返回最先被 reject 失败状态的值

CustomPromise 增加动态 all()办法

  // 动态的 all 办法
  static all(values){let result = [];
    let index = 0;
    return new CustomPromise((resolve,reject) => {function addPromise(key, value) {result[key] = value
        index++
        if (index === values.length) {resolve(result)
        }
      }
      
      for(let i = 0; i < values.length; i++){let item = values[i];
        if(item instanceof CustomPromise){
          // 参数为 Promise
          item.then(value => addPromise(i,value), error => reject(reason))
        }else{
          // 参数为一般值
          addPromise(i,item)
        }
      }
    })
  }

那咱们来验证下

let p1 = new CustomPromise((resolve, reject) => {resolve("start");
});
let p2 = new CustomPromise((resolve, reject) => {resolve("hellow");
});
let p3 = new CustomPromise((resolve, reject) => {resolve("promise");
});
​
CustomPromise.all([p1, p2, p3])
  .then((res) => console.log("success:", res))
  .catch((err) => console.log("error:", err));
// 输入后果 success:['start', 'hellow', 'promise']
let p1 = new CustomPromise((resolve, reject) => {resolve("start");
}).then((res) => res);
let p2 = new CustomPromise((resolve, reject) => {reject("报错了");
}).then((res) => res);
let p3 = new CustomPromise((resolve, reject) => {reject("报错了 2");
}).then((res) => res);
​
CustomPromise.all([p1, p2, p3])
  .then((res) => console.log("success:", res))
  .catch((err) => console.log("error:", err));
// 输入后果 error: 报错了

Promise.race()

Promise.race()办法返回一个 promise,一旦迭代器中的某个 promise 解决或回绝,返回的 promise 就会解决或回绝。

var p1 = new Promise(function(resolve, reject) {setTimeout(resolve, 300, "start");
});
var p2 = new Promise(function(resolve, reject) {setTimeout(resolve, 100, "hellow");
});
​
const p = Promise.race([p1, p2]).then(function(value) {console.log(value); // "hellow"
});

来剖析下那就是有一个实例先扭转状态,p 的状态就跟着扭转

CustomPromise 增加动态 race()办法

// 动态 race 办法
  static race(values) {return new CustomPromise((resolve, reject) => {for (const p of values) {p.then(resolve, reject);
      }
    });
  }

那咱们来验证下

var p1 = new CustomPromise(function(resolve, reject) {setTimeout(resolve, 300, "start");
});
var p2 = new CustomPromise(function(resolve, reject) {setTimeout(resolve, 100, "hellow");
});
​
const p = CustomPromise.race([p1, p2]).then(function(value) {console.log(value); // "hellow"
});

Promise.allSettled()

Promise.allSettled() 办法 不依赖于彼此胜利实现的异步工作,不论每一个操作是胜利还是失败,再进行下一步操作。

Promise.allSettled([Promise.resolve('start'),
  Promise.reject(new Error("error")),
  new Promise((resolve) => setTimeout(() => resolve('hellow'), 0)),
  'promise',
]).then((values) => console.log(values));
​
// [//   { status: 'fulfilled', value: start},
//   {status: 'rejected', reason: Error: error},
//   {status: 'fulfilled', value: hellow},
//   {status: 'fulfilled', value: promise}
// ]

来剖析下后果

  • status 一个字符串,要么是 "fulfilled",要么是 "rejected",示意 promise 的最终状态。
  • value 当 status"fulfilled",在 promise 解决时才有 value
  • reason 当 status"rejected",在 promsie 回绝时才有 reason

CustomPromise 增加动态 allSettled()办法

// 动态 allSettled 办法
  static allSettled(values) {return new Promise((resolve, reject) => {let resolveDataList = [],
        resolveCount = 0;
      const addPromise = (status, value, i) => {resolveDataList[i] = {
          status,
          value,
        };
        resolveCount++;
        if (resolveCount === values.length) {resolve(resolveDataList);
        }
      };
      values.forEach((value, i) => {if (value instanceof CustomPromise) {
          value.then((res) => {addPromise("fulfilled", res, i);
            },
            (err) => {addPromise("rejected", err, i);
            }
          );
        } else {addPromise("fulfilled", value, i);
        }
      });
    });
  }

来验证下

CustomPromise.allSettled([CustomPromise.resolve('start'),
  CustomPromise.reject(new Error("error")),
  new CustomPromise((resolve) => setTimeout(() => resolve('hellow'), 0)),
  'promise',
]).then((values) => console.log(values));
​
// [//   { status: 'fulfilled', value: start},
//   {status: 'rejected', reason: Error: error},
//   {status: 'fulfilled', value: hellow},
//   {status: 'fulfilled', value: promise}
// ]

Promise.any()

Promise.any()接管一个由 Promise 所组成的可迭代对象,返回一个新的promise

const p1 = new Promise((resolve, reject) => {setTimeout(resolve, 100, "start");
});
​
const p2 = new Promise((resolve, reject) => {reject("报错了");
});
​
const p3 = new Promise((resolve, reject) => {setTimeout(resolve, 500, "promise");
});
​
Promise.any([p1, p2, p3]).then((value) => {console.log(value);
  // start
})
const p1 = new Promise((resolve, reject) => {setTimeout(reject, 100, "start");
});
​
const p2 = new Promise((resolve, reject) => {reject("报错了");
});
​
const p3 = new Promise((resolve, reject) => {setTimeout(reject, 500, "promise");
});
​
Promise.any([p1, p2, p3])
  .then((value) => {console.log("value:", value);
  })
  .catch((err) => {console.log("err:", err); //err: AggregateError: All promises were rejected
  });
​

那咱们来剖析下

  • 与 all()不同,只有有一个 promise 胜利,会返回首个胜利的 promise 的值,办法提前结束
  • 如果所有 Promise 都失败,则报错 All promises were

CustomPromise 增加动态 any()办法

// 动态 any 办法
  static any(values) {return new CustomPromise((resolve, reject) => {
      let rejectCount = 0;
      values.forEach((value) => {
        value.then((val) => resolve(val),
          (err) => {
            rejectCount++;
            if (rejectCount === value.length) {reject("All promises were rejected");
            }
          }
        );
      });
    });
  }

咱们来验证下

const p1 = new CustomPromise((resolve, reject) => {setTimeout(resolve, 100, "start");
});
​
const p2 = new CustomPromise((resolve, reject) => {reject("报错了");
});
​
const p3 = new CustomPromise((resolve, reject) => {setTimeout(resolve, 500, "promise");
});
​
CustomPromise.any([p1, p2, p3])
  .then((value) => {console.log("value:", value); //value: start
  })
  .catch((err) => {console.log("err:", err);
  });
const p1 = new CustomPromise((resolve, reject) => {setTimeout(reject, 100, "start");
});
​
const p2 = new CustomPromise((resolve, reject) => {reject("报错了");
});
​
const p3 = new CustomPromise((resolve, reject) => {setTimeout(reject, 500, "promise");
});
​
CustomPromise.any([p1, p2, p3])
  .then((value) => {console.log("value:", value);
  })
  .catch((err) => {console.log("err:", err); //err: All promises were rejected
  });

残缺代码

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
​
class CustomPromise {constructor(executor) {
    try {executor(this.resolve, this.reject);
    } catch (error) {
      // 如果有谬误,就间接执行 reject
      this.reject(error);
    }
  }
  // resolve 和 reject 为什么要用箭头函数?// 如果间接调用的话,一般函数 this 指向的是 window 或者 undefined
  // 用箭头函数就能够让 this 指向以后实例对象
  resolve = (value) => {
    // promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled
    if (this.status == PENDING) {
      this.status = FULFILLED;
      this.value = value;
​
      // resolve 外面将所有胜利的回调拿进去执行
      if (this.onResolvedCallbacks.length) {this.onResolvedCallbacks.forEach((fn) => fn());
      }
    }
  };
  reject = (err) => {
    // promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled
    if (this.status == PENDING) {
      this.status = REJECTED;
      this.reason = err;
      // reject 外面将所有失败的回调拿进去执行
      if (this.onFulfilledCallbacks.length) {this.onFulfilledCallbacks.forEach((fn) => fn());
      }
    }
  };
  // 存储胜利回调函数
  onResolvedCallbacks = [];
  // 存储失败回调函数
  onFulfilledCallbacks = [];
​
  status = PENDING;
  // 胜利之后的值
  value = undefined;
  // 失败之后的值
  reason = undefined;
​
  then(onFulfilled, onRejected) {
    // 如果不传,就应用默认函数, 确保是函数类型
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {throw reason;};
​
    const thenCustomPromise = new CustomPromise((resolve, reject) => {const resolveCustomPromise = (callBack, value) => {
        try {const x = callBack(value);
          // 如果相等了,阐明 return 的是本人,抛出类型谬误并返回
          if (resolveCustomPromise === x) {return reject(new TypeError("类型谬误"));
          }
          // 判断 x 是不是 CustomPromise 实例对象
          if (x instanceof CustomPromise) {
            // 执行 x,调用 then 办法,目标是将其状态变为 fulfilled 或者 rejected
            // x.then(value => resolve(value), error => reject(reason))
            // 简化之后
            x.then(resolve, reject);
          } else {
            // 一般值
            resolve(x);
          }
        } catch (error) {reject(error);
        }
      };
      // 须要判断状态,依据状态抉择解决回调函数
      if (this.status == FULFILLED) {resolveCustomPromise(onFulfilled, this.value);
      } else if (this.status == REJECTED) {resolveCustomPromise(onRejected, this.reason);
      } else if (this.status == PENDING) {
        // 当状态为 pending 时, 把 then 回调 push 进 resolve/reject 执行队列, 期待执行
        this.onResolvedCallbacks.push(() =>
          resolveCustomPromise(onFulfilled, this.value)
        );
        this.onFulfilledCallbacks.push(() =>
          resolveCustomPromise(onRejected, this.reason)
        );
      }
    });
    return thenCustomPromise;
  }
  catch(onFulfilled) {return this.then(null, onFulfilled);
  }
  finally(callback) {
    return this.then((value) => CustomPromise.resolve(callback()).then(() => value),
      (reason) => CustomPromise.resolve(callback()).then(() => reason)
    );
  }
  // 动态的 resolve 办法
  static resolve(value) {if (value instanceof CustomPromise) return value;
    return new CustomPromise((resolve) => resolve(value));
  }
  // 动态的 reject 办法
  static reject(reason) {return new CustomPromise((resolve, reject) => reject(reason));
  }
  // 动态的 all 办法
  static all(values) {
    // 用来记录 Promise 胜利的次数
    let resolveCount = 0,
      // 用来保留 Promise 胜利的后果
      resolveDataList = [];
    return new CustomPromise((resolve, reject) => {function addPromise(key, value) {resolveDataList[key] = value;
        resolveCount++;
        if (resolveCount === values.length) {resolve(resolveDataList);
        }
      }
​
      for (let i = 0; i < values.length; i++) {let item = values[i];
        if (item instanceof CustomPromise) {
          // 参数为 Promise
          item.then((value) => addPromise(i, value),
            (error) => reject(error)
          );
        } else {
          // 参数为一般值
          addPromise(i, item);
        }
      }
    });
  }
  // 动态 race 办法
  static race(values) {return new CustomPromise((resolve, reject) => {for (const p of values) {p.then(resolve, reject);
      }
    });
  }
  // 动态 allSettled 办法
  static allSettled(values) {return new Promise((resolve, reject) => {let resolveDataList = [],
        resolveCount = 0;
      const addPromise = (status, value, i) => {resolveDataList[i] = {
          status,
          value,
        };
        resolveCount++;
        if (resolveCount === values.length) {resolve(resolveDataList);
        }
      };
      values.forEach((value, i) => {if (value instanceof CustomPromise) {
          value.then((res) => {addPromise("fulfilled", res, i);
            },
            (err) => {addPromise("rejected", err, i);
            }
          );
        } else {addPromise("fulfilled", value, i);
        }
      });
    });
  }
  // 动态 any 办法
  static any(values) {return new CustomPromise((resolve, reject) => {
      let rejectCount = 0;
      values.forEach((value) => {
        value.then((val) => resolve(val),
          (err) => {
            rejectCount++;
            if (rejectCount === value.length) {reject("All promises were rejected");
            }
          }
        );
      });
    });
  }
}

结语

对于 Promise 的实现就到这里了,心愿能跟大家一起提高⛽️⛽️⛽️

如果写的有问题,欢送大家指出问题,一起探讨,让我再打磨打磨

最初呢,心愿大家反对一下 长文不易 记得给点个赞👍👍👍

退出移动版