文章目录
本篇文章,你能通过手动实现一个
Promise
来更加深刻的掌握它的机制,文章最后我们通过一些经典的例子巩固它在实际中的应用。后续我们会有专门的篇章来介绍
Promise应用
。
在开始动手实现 Promise前,我们先来熟悉一些术语:
promise
是一个有 then 方法的对象或者是函数,行为遵循本PromiseA+规范thenable
是一个有 then 方法的对象或者是函数value
是 promise 状态成功时的值,也就是 resolve 的参数, 包括各种数据类型, 也包括 undefined/thenable 或者是 promisereason
是 promise 状态失败时的值, 也就是 reject 的参数, 表示拒绝的原因exception
是一个使用 throw 抛出的异常值
Promise是啥?
Promise
是对 PromiseA+
规范的一种实现。对此规范不了解的,可以去查阅相关资料。
Promise 有三种状态
-
pending
1.1 初始的状态, 可改变.
1.2 一个 promise 在 resolve 或者 reject 前都处于这个状态。
1.3 可以通过 resolve -> fulfilled 状态;
1.4 可以通过 reject -> rejected 状态; -
fulfilled
2.1 最终态, 不可变.
2.2 一个 promise 被 resolve 后会变成这个状态.
2.3 必须拥有一个 value 值 -
rejected
3.1 最终态, 不可变.
3.2 一个 promise 被 reject 后会变成这个状态
3.3 必须拥有一个 reason
总结一下, promise 的状态流转
pending -> resolve(value) -> fulfilled
pending -> reject(reason) -> rejected
promise 提供一个 then 方法, 用来访问最终的结果, 无论是 value 还是 reason.
promise.then(onFulfilled, onRejected);
模拟实现 Promise
现在,我们来分析一下,实现 Promise 我们需要哪些步骤:
- Promise的构造函数
new Promise()
; - 类成员方法
then()、catch()、finally()
; - 实现类的静态方法
Promise.all、Promise.race、Promise.allSettled、Promise.any
; - 实现链式调用
resolvePromise()
回顾一下我们是如何使用它的,通过传一个回调函数去实例化一个promise,回调函数会立即执行;
new Promise((resolve,reject) => {
// 立即执行
})
先来定义一个 MPromise 类, 定义 fulfilledCallbackList 和 rejectedCallbackList
用来接受成功或者失败后的毁掉函数。在构造器函数中,定义初始状态为 PENDING
, 在 try...catch
块中立即执行了通过new Promise(fn)
传入的函数,这也解释了我们上面的代码。同时我们定义决议函数resolve和reject
,这两个函数主要是,判断当前状态是否处于PENDING
状态(避免二次决议),设置相对应的值。
这里我们通过getter setter 监听状态的改变,来执行决议之后的回调;这里我们需要注意的是,在resolve 和 reject
方法中,我们要先赋值再变更状态。
class MPromise {
fulfilledCallbackList = []; // 成功后执行cb队列
rejectedCallbackList = []; // 失败后执行cb队列
_status = PENDING;
constructor(fn) {
// 初始状态为pending, promise成功时的值value,失败时的值reason
this.status = PENDING;
this.value = null;
this.reason = null;
// 状态流转,pending ——》resolve(value) ——》fulfilled
const resolve = (value) => {
if (this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
}
};
// 状态流转,pending ——》reject(reason) ——》rejected
const reject = (reason) => {
if (this.status ==