返回

手写Promise:揭秘实现机制与过程,深入理解Promise核心要点

前端

了解 Promise 核心代码,是掌握异步编程的关键一步。Promise,作为处理异步操作的强有力工具,能帮助我们轻松处理回调函数,使代码更加整洁易读。下面,我们就来手把手地编写 Promise 核心代码,并深入理解 Promise 的实现机制与过程。

一、Promise 的设计思路

首先,我们来了解 Promise 的设计思路。Promise 本质上是一个对象,它拥有三种状态:Pending、Fulfilled 和 Rejected。Pending 表示 Promise 处于等待状态,Fulfilled 表示 Promise 已完成并成功执行,Rejected 表示 Promise 已完成但执行失败。

二、Promise 核心代码实现

接下来,我们就来实现 Promise 的核心代码。

class Promise {
  constructor(executor) {
    this.state = "pending"; // 初始状态为 Pending
    this.value = undefined; // 存储执行成功后的值
    this.reason = undefined; // 存储执行失败后的原因
    this.onFulfilledCallbacks = []; // 存储成功的回调函数
    this.onRejectedCallbacks = []; // 存储失败的回调函数

    // 立即执行 executor,将 resolve 和 reject 传递进去
    try {
      executor(this.resolve, this.reject);
    } catch (error) {
      this.reject(error); // executor 执行时出错,直接进入 Rejected 状态
    }
  }

  resolve(value) {
    // 检查状态是否为 Pending
    if (this.state !== "pending") {
      return;
    }

    // 将状态从 Pending 转换为 Fulfilled
    this.state = "fulfilled";

    // 将成功的结果保存起来
    this.value = value;

    // 执行所有成功的回调函数
    this.onFulfilledCallbacks.forEach((callback) => callback(value));
  }

  reject(reason) {
    // 检查状态是否为 Pending
    if (this.state !== "pending") {
      return;
    }

    // 将状态从 Pending 转换为 Rejected
    this.state = "rejected";

    // 将失败的原因保存起来
    this.reason = reason;

    // 执行所有失败的回调函数
    this.onRejectedCallbacks.forEach((callback) => callback(reason));
  }

  then(onFulfilled, onRejected) {
    // 处理 onFulfilled 为非函数的情况
    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (value) => value;

    // 处理 onRejected 为非函数的情况
    onRejected = typeof onRejected === "function" ? onRejected : (reason) => { throw reason; };

    const promise2 = new Promise((resolve, reject) => {
      // 如果状态为 Fulfilled,执行 onFulfilled 并将结果传递给下一个 Promise
      if (this.state === "fulfilled") {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0);
      }

      // 如果状态为 Rejected,执行 onRejected 并将原因传递给下一个 Promise
      if (this.state === "rejected") {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0);
      }

      // 如果状态为 Pending,将回调函数保存起来,等待状态改变后再执行
      if (this.state === "pending") {
        this.onFulfilledCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        });

        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        });
      }
    });

    return promise2;
  }
}

// 处理 then 返回值的 Promise 的情况
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    reject(new TypeError("循环引用"));
  }

  if (x instanceof Promise) {
    x.then((y) => {
      resolvePromise(promise2, y, resolve, reject);
    }, reject);
  } else if (x !== null && (typeof x === "object" || typeof x === "function")) {
    try {
      const then = x.then;

      if (typeof then === "function") {
        then.call(
          x,
          (y) => {
            resolvePromise(promise2, y, resolve, reject);
          },
          (r) => {
            reject(r);
          }
        );
      } else {
        resolve(x);
      }
    } catch (error) {
      reject(error);
    }
  } else {
    resolve(x);
  }
}

三、Promise 的使用

现在,我们已经了解了 Promise 的核心代码,接下来就让我们看看如何使用 Promise。

// 创建一个 Promise
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Hello, World!"); // 将结果传递给 resolve 函数
  }, 2000);
});

// 使用 then 方法处理 Promise 的结果
promise.then((result) => {
  console.log(result); // 输出 "Hello, World!"
}, (reason) => {
  console.log(reason); // 如果 Promise 失败,则输出失败的原因
});

结语

通过手写 Promise 的核心代码,我们深入理解了 Promise 的内部机制和工作原理。这不仅有助于我们更好地掌握异步编程,也能让我们更加灵活地使用 Promise,轻松处理复杂的异步操作。希望这篇文章对您有所帮助,也欢迎您继续探索 Promise 的更多用法。