前言
本文以 ECMA-262 标准中 Promise 部分为参考,利用 ES6 语法对 Promise 进行实现,读完本文应能提升对 Promise 内部机制的了解,前提是已经对 Promise 用法有一定了解,本文不再赘述。
名词定义
此处定义在下方实现中出现的一系列名词的简单解释
构造函数名
本文为了防止冲突,使用 MPromise 作为构造函数名(M 就是 Mondo 啦~)
状态
Promise 自身状态
- fulfilled
已经被解决的状态,在此状态下调用 then(onFulfilled, onRejected) 将会直接调用 onFulfilled 函数 - rejected
类似 fulfilled 状态,但调用的是 onRejected - pending
既不处于 fulfilled 也不处于 rejected 的状态
衍生状态
settled
处于 fulfilled 或 rejected 状态resolved
处于 settled 状态或处于无法通过 resolve / reject 函数改变状态的状态在阮一峰第二版 ES6 入门中混淆了 resolved 状态和 fulfilled 状态,此处解释遵循 ECMA-262 标准中解释
1
2
3
4
5
6
7
8
9new MPromise((resolve, reject) => {
setTimeout(resolve, 1000, 'inside')
}) // => 返回 promise-1 对象
.then(() => {
// promise-1 进入 resolved 状态,但其自身 state 仍处于 pending
return new MPromise((resolve, reject) => {
setTimeout(resolve, 1000, 'second inside')
})
}) // => 返回 promise-2 对象
函数名
executor
传入构造函数中的函数,接受 resolve 和 reject 函数作为参数
resolve & reject
用于传入 executor 中,或用于 resolve / reject 处于 resolved 锁定状态的 promise
onFulfilled & onRejected (handler)
传入 then 函数中的函数,一般为用户外部定义,在 promise 状态处于 settled 时会按顺序被调用,其中的返回值将作为 then 创建的新 promise 的 result
一个非用户定义的例子为在这两个函数返回新的内部 promise 时,将 then 新建的传递给外部的 promise 的 resolve & reject 函数作为内部 promise 的 onFulfilled & onRejected 函数
特殊封装对象
PromiseCapability
一组 promise 和改变该 promise 状态函数的封装对象,结构如下
1 | { |
PromiseReaction
一组对 capability 和 handler 的封装,结构如下
1 | { |
通用函数及常量
该部分函数为不包含在 Promise 部分的抽象操作,此处处理为函数
1 | /** |
构造函数、实例方法及相关操作
Promise(executor)
按 ES6 标准,该构造函数必须通过 new 关键字实例化,并且支持继承。
当 Promise 被调用时,代码和流程如下:
1 | constructor(executor) { |
CreateResolvingFunctions(promise)
该函数用于创建与 promise 绑定的两个 resolve、reject 方法,这两个方法用于传入 executor 中,其流程如下:
1 | /** |
FulfillPromise(promise, reason) & RejectPromise(promise, reason)
1 | /** |
TriggerPromiseReactions(reactions, argument) & PromiseReactionJob(reaction, argument)
1 | /** |
PromiseResolveThenableJob(promiseToResolve, thenable, then)
1 | /** |
Promise#then & PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability)
then 作为 Promise 的核心方法,是 Promise 解决回调嵌套和精髓之处,本文的实例方法也只暂包含这一个方法。通过该方法可轻松实现 Promise#catch
等其他一系列实例或类方法
1 | then(onFulfilled, onRejected) { |
NewPromiseCapability(C)
1 | /** |
后记
本文主要根据标准逻辑进行了实现,函数结构和命名保持和 ES6 标准完全一致,配合食用更佳,在下文中,将会理清这些函数间的调用关系,欢迎关注。
全文代码在此仓库可见,欢迎 star fork 提 issue