返回

Promise 的手写实现

前端

前言

Promise 是一种用于处理异步编程的 JavaScript 对象,它允许我们以更优雅和可读的方式处理异步操作的结果。虽然 Promise 在现代 JavaScript 中无处不在,但理解其底层的工作原理可以帮助我们更有效地使用它。

状态的定义

Promise 的核心是一个内部状态,它可以是以下三种之一:

  • Pending(待定): Promise 尚未完成或失败。
  • Fulfilled(已完成): Promise 已成功完成,并带有结果值。
  • Rejected(已拒绝): Promise 已失败,并带有错误原因。

改变状态的方法

Promise 提供了两个改变其状态的方法:

  • resolve(): 将 Promise 标记为已完成,并设置其结果值。
  • reject(): 将 Promise 标记为已拒绝,并设置其错误原因。

then 方法

then() 方法允许我们为 Promise 指定回调函数,这些回调函数将在 Promise 改变状态时执行。then() 方法有两个参数:

  • onFulfilled(): 在 Promise 已完成时调用的回调函数。
  • onRejected(): 在 Promise 已拒绝时调用的回调函数。

resolvePromise 解析

resolvePromise() 是一个辅助函数,用于解析 Promise 的值。当 then() 回调函数返回一个 Promise 时,resolvePromise() 会自动解析该 Promise 并将结果传递给下一个 then() 回调函数。

手写实现

现在,让我们一步步手写实现 Promise:

function Promise(executor) {
  // 内部状态
  this.state = 'pending';

  // 结果值
  this.value = undefined;

  // 错误原因
  this.reason = undefined;

  // 存储 then 回调函数
  this.onFulfilledCallbacks = [];
  this.onRejectedCallbacks = [];

  // 改变状态的方法
  const resolve = (value) => {
    if (this.state !== 'pending') return;

    this.state = 'fulfilled';
    this.value = value;

    // 执行 then 回调函数
    this.onFulfilledCallbacks.forEach(callback => callback(value));
  };

  const reject = (reason) => {
    if (this.state !== 'pending') return;

    this.state = 'rejected';
    this.reason = reason;

    // 执行 then 回调函数
    this.onRejectedCallbacks.forEach(callback => callback(reason));
  };

  // then 方法
  this.then = (onFulfilled, onRejected) => {
    return new Promise((resolve, reject) => {
      // 处理 onFulfilled 回调函数
      if (onFulfilled) {
        this.onFulfilledCallbacks.push(() => {
          try {
            // 捕获任何错误
            const result = onFulfilled(this.value);

            // 解析结果 Promise
            resolvePromise(result, resolve, reject);
          } catch (error) {
            reject(error);
          }
        });
      }

      // 处理 onRejected 回调函数
      if (onRejected) {
        this.onRejectedCallbacks.push(() => {
          try {
            // 捕获任何错误
            const result = onRejected(this.reason);

            // 解析结果 Promise
            resolvePromise(result, resolve, reject);
          } catch (error) {
            reject(error);
          }
        });
      }
    });
  };

  // 执行 executor 函数
  executor(resolve, reject);
}

示例用法

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功!');
  }, 1000);
});

promise.then((result) => {
  console.log('成功结果:', result);
}).catch((reason) => {
  console.error('失败原因:', reason);
});

总结

我们已经从零开始手写实现了 Promise。通过理解其状态管理、改变状态的方法、then() 方法和 resolvePromise() 解析,我们现在可以更好地理解 Promise 在异步编程中的强大作用。手写实现是一个很好的练习,可以帮助我们深入了解 Promise 的内部运作原理。