Promise 的模拟实现

248 阅读6分钟

1. Promise constructor 的初步实现

constructor(executor) {
  // 初始化 Promise 实例对象的状态 state 和结果 result
  this.state = "pending"
  this.result = undefined 

  // 方法内部实现 resolve 和 reject 两个方法改变 Promise 实例对象的 state 和 result
  const resolve = (result) => {
    // 当且仅当 Promise 实例对象的状态 state 为 pending 时
    // 才能够改变 Promise 实例对象的状态 state 和结果 result
    if (this.state === "pending") {
      this.state = "fulfilled"
      this.result = result
    }
  }

  const reject = (reason) => {
    if (this.state === "pending") {
      this.state = "rejected"
      this.result = reason
    }
  }

  // 如果 executor 执行的过程中出错
  // 则直接调用 reject 将错误原因作为 Promise 的 result
  try {
    executor(resolve, reject)
  } catch(e) {
    reject(e)
  }
}

2. Promise.then 的初步实现

  • 对 constructor 中的代码进行修改

    constructor(executor) {
      ...
      // Promise 实例对象的等待队列
      // 当调用 then 方法而 Promise 实例对象的 state 还没有确定时
      // 将调用 then 方法时传入的两个参数 onFulfilled 和 onRejected 的异步执行过程加入等待队列
      // 待到 Promise 实例对象的 state 确定之后, 全部调用
      this.onFulfilledCallbacks = []
      this.onRejectedCallbacks = []
    
      const resolve = (result) => {
        if (this.state === "pending") {
          this.state = "fulfilled"
          this.result = result
          // 当 Promise 实例对象的 state 确定为 fulfilled 时
          // 调用 onFulfilledCallbacks 中的所有方法
          this.onFulfilledCallbacks.forEach(fn => fn())
        }
      }
    
      const reject = (reason) => {
        if (this.state === "pending") {
          this.state = "fulfilled"
          this.result = reason
          // 当 Promise 实例对象的 state 确定为 rejected 时
          // 调用 onRejectedCallbacks 中的所有方法
          this.onRejectedCallbacks.forEach(fn => fn())
        }
      }
      ...
    }
    
  • then 方法的初步实现

    then(onFulfilled, onRejected) {
      // 当调用 then 方法的 Promise 实例对象的 state 被确定后
      // 异步调用 onFulfilled / onRejected 方法
      if (this.state === "fulfilled") {
        setTimeout(() => {
          onFulfilled(this.result)
        })
      } else if (this.state === "rejected") {
        setTimeout(() => {
          onRejected(this.result)
        })
      }
      // 如果 Promise 实例对象的 state 还没有确定
      // 则将异步执行 onFulfilled / onRejected 方法的过程包装成函数添加到 Promise 的等待队列中
      else if (this.state === "fulfilled") {
        this.onFulfilledCallbacks.push(() => {
          setTimeout(() => {
            onFulfilled(this.result)
          })
        })
        this.onRejecetedCallbacks.push(() => {
          setTimeout(() => {
            onRejected(this.result)
          })
        })
      }
    }
    
  • 实现 then 方法的链式调用

    then(onFulfilled, onRejected) {
      // 若 onFulfilled 或 onRejected 不是函数
      // 则 then 返回的 Promise 实例对象的 state 与 result 和 this 的一样
      if (typeof onFulfilled !== "function") {
        onFulfilled = (result) => result
      }
      if (typeof onRejected !== "function") {
        onRejected = (reason) => {throw reason}
      }
    
      // 构建 then 将要返回的 Promise 实例对象
      const promise2 = new Promise((resolve, reject) => {
        // resolvePromise 方法用于处理 onFulfilled / onRejected 返回的值 x
        // 如果 x 是 Promise 实例对象, 则继承其 state 与 result
        // 否则, then 返回的 Promise 实例对象的 result 就是 x
        // 若是在执行 resolvePromise 的过程中出现 error, 则 result = error
        if (this.state === "fulfilled") {
          setTimeout(() => {
            try {
              const x = onFulfilled(this.result)
              resolvePromise(x, promise2, resolve, reject)
            } catch(e) {
              reject(e)
            }
          })
        } else if (this.state === "rejected") {
          setTimeout(() => {
            try {
              const x = onRejected(this.result)
              resolvePromise(x, promise2, resolve, reject)
            } catch(e) {
              reject(e)
            }
          })
        } else if (this.state === "pending") {
          this.onFulfilled.push(() => {
            setTimeout(() => {
              try {
                const x = onFulfilled(this.result)
                resolvePromise(x, promise2, resolve, reject)
              } catch(e) {
                reject(e)
              }
            })
          })
          this.onRejected.push(() => {
            setTimeout(() => {
              try {
                const x = onRejected(this.result)
                resolvePromise(x, promise2, resolve, reject)
              } catch(e) {
                reject(e)
              }
            })
          })
        }  
      })
    
      return promise2
    }
    
  • resolvePromise 方法的实现

    function resolvePromise(x, promise2, resolve, reject) {
      // 防止出现 let p = promiseObj.then(result => p, reason => p) 的情况
      if (x === promise2) {
        reject(new TypeError("err"))
      }
    
      // 区分 Promise 实例对象的第一步
      if (typeof x === "object" && x !== null || typeof x === "function") {
        // 记录调用次数, 保证仅调用一次 resolve 或 reject
        let called = false
    
        try {
          const then = x.then
          // 区分 Promise 实例对象的第二步
          if (typeof then === "function") {
            // 如果 x 是 Promise 实例对象, 则通过 .then 来获取其 state 和 result
            then.call(x, (result) => {
              if (called) return
              called = true
    
              // 若 x 的 result 为 Promise 对象, 则递归解开, 直到获取非 Promise 对象
              resolvePromise(result, promise2, resolve, reject)
            }, (reason) => {
              if (called) return
              called = true
    
              reject(reason)
            })
          } else {
            // 如果 x 是普通对象或函数
            // 则 x 即作为 then 方法返回的 Promise 实例对象的 result
            resolve(x)
          }
        } catch(e) {
          if (called) return
          called = true
    
          reject(e)
        }
      } else {
        // 如果 x 既不是对象又不是函数
        // 则 x 即作为 then 方法返回的 Promise 实例对象的 result
        resolve(x)
      }
    }
    

3. Promise 的最终实现

function resolvePromise(x, promise2, resolve, reject) {
  // 防止出现 let p = promiseObj.then(result => p, reason => p) 的情况
  if (x === promise2) {
    reject(new TypeError("err"))
  }

  // 区分 Promise 实例对象的第一步
  if (typeof x === "object" && x !== null || typeof x === "function") {
    // 记录调用次数, 保证仅调用一次 resolve 或 reject
    let called = false

    try {
      const then = x.then
      // 区分 Promise 实例对象的第二步
      if (typeof then === "function") {
        // 如果 x 是 Promise 实例对象, 则通过 .then 来获取其 state 和 result
        then.call(x, (result) => {
          if (called) return
          called = true

          // 若 x 的 result 为 Promise 对象, 则递归解开, 直到获取非 Promise 对象
          resolvePromise(result, promise2, resolve, reject)
        }, (reason) => {
          if (called) return
          called = true

          reject(reason)
        })
      } else {
        // 如果 x 是普通对象或函数
        // 则 x 即作为 then 方法返回的 Promise 实例对象的 result
        resolve(x)
      }
    } catch(e) {
      if (called) return
      called = true

      reject(e)
    }
  } else {
    // 如果 x 既不是对象又不是函数
    // 则 x 即作为 then 方法返回的 Promise 实例对象的 result
    resolve(x)
  }
}

class Promise {
  constructor(executor) {
    // 初始化 Promise 实例对象的 state 和 result
    this.state = "pending"
    this.result = undefined

    // Promise 实例对象的等待队列
    // 当调用 then 方法而 Promise 实例对象的 state 还没有确定时
    // 将调用 then 方法时传入的两个参数 onFulfilled 和 onRejected 的异步执行过程加入等待队列
    // 待到 Promise 实例对象的 state 确定之后, 全部调用
    this.onFulfilledCallbacks = []
    this.onRejectedCallbacks = [] 

    const resolve = (result) => {
      if (this.state === "pending") {
        this.state = "fulfilled"
        this.result = result

        // 当 Promise 实例对象的 state 确定为 fulfilled 时
        // 调用 onFulfilledCallbacks 中的所有方法
        this.onFulfilledCallbacks.forEach(fn => fn())
      }
    }

    const reject = (reason) => {
      if (this.state === "pending") {
        this.state = "rejected"
        this.result = reason

        // 当 Promise 实例对象的 state 确定为 rejected 时
        // 调用 onRejectedCallbacks 中的所有方法
        this.onRejectedCallbacks.forEach(fn => fn())
      }
    }

    // 如果传入的方法执行时出错
    // 则将出错情况作为 Promise 实例对象的 result
    try {
      executor(resolve, reject)
    } catch(e) {
      reject(e)
    }
  }

  then(onFulfilled, onRejected) {
    // 若 onFulfilled 或 onRejected 不是函数
    // 则 then 返回的 Promise 实例对象的 state 与 result 和 this 的一样
    if (typeof onFulfilled !== "function") {
      onFulfilled = (result) => result
    }
    if (typeof onRejected !== "function") {
      onRejected = (reason) => {throw reason}
    }

    // 构建 then 将要返回的 Promise 实例对象
    const promise2 = new Promise((resolve, reject) => {
      // resolvePromise 方法用于处理 onFulfilled / onRejected 返回的值 x
      // 如果 x 是 Promise 实例对象, 则继承其 state 与 result
      // 否则, then 返回的 Promise 实例对象的 result 就是 x
      // 若是在执行 resolvePromise 的过程中出现 error, 则 result = error
      if (this.state === "fulfilled") {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.result)
            resolvePromise(x, promise2, resolve, reject)
          } catch(e) {
            reject(e)
          }
        })
      } else if (this.state === "rejected") {
        setTimeout(() => {
          try {
            const x = onRejected(this.result)
            resolvePromise(x, promise2, resolve, reject)
          } catch(e) {
            reject(e)
          }
        })
      } else if (this.state === "pending") {
        this.onFulfilledCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onFulfilled(this.result)
              resolvePromise(x, promise2, resolve, reject)
            } catch(e) {
              reject(e)
            }
          })
        })
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onRejected(this.result)
              resolvePromise(x, promise2, resolve, reject)
            } catch(e) {
              reject(e)
            }
          })
        })
      }  
    })

    return promise2
  }
}

4. Promise.prototype.catch

catch(onRejected) {
  return this.then(null, onRejected)
}

5. Promise.prototype.finally

finally(onFinally) {
  // 无条件执行 onFinally 方法的同时, 不会使用上一个 Promise 实例对象的 result
  // 当 onFinally 方法执行出错时, 返回的 Promise 实例对象的 result 就是错误
  // 否则返回的 Promise 实例对象的 result 和 state 相较执行 finally 之前没有改变
  return this.then((result) => {
    return Promise.resolve(onFinally()).then(() => result)
  }, (reason) => {
    return Promise.resolve(onFinally()).then(() => {throw reason})
  })
}

6. Promise.resolve, Promise.reject

static resolve(result) {
  // 如果传递的参数是 Promise 实例, 则直接返回实例
  // 否则返回用 Promise 包装后的参数
  if (result instanceof Promise) {
    return result
  } else {
    return new Promise((resolve, reject) => {
      resolve(result)
    })
  }
}

static reject(reason) {
  if (reason instanceof Promise) {
    return reason
  } else {
    return new Promise((resolve, reject) => {
      reject(reason)
    })
  }
}

7. Promise.all

static all(promises) {
  const result = []
  let counter = 0
  return new Promise((resolve, reject) => {
    for (let i = 0, len = promises.length; i < len; i ++) {
      // 由于不知道 promises[i] 究竟是不是 Promise 实例
      // 故都用 Promise.resolve 包装起来就不用分类讨论了
      Promise.resolve(promises[i]).then((res) => {
        result[i] = res
        if (++ counter === len) {
          resolve(result)
        }
      }, reject)
    }
  })
}

8. Promise.race

static race(promises) {
  return new Promise((resolve, reject) => {
    for (let i = 0, len = promises.length; i < len; i ++) {
      // 遇到有状态的 Promise 实例或者非 Promise
      // 直接改变 race 返回的 Promise 的状态
      Promise.resolve(promises[i]).then(resolve, reject)
    }
  })
}