返回

Promise 解密:从概念到实现

前端

在现代 JavaScript 开发中,Promise 已成为异步编程的标配。它提供了一种更优雅的方式来处理异步操作,让我们可以轻松地编写出可读性高、可维护性强的代码。然而,要真正掌握 Promise,就需要对它的内部机制有深入的了解。

Promise 的概念

Promise 是一个对象,它表示一个异步操作的最终完成或失败及其结果值。它有三种状态:

  • 待定(pending):表示操作尚未完成。
  • 已完成(fulfilled):表示操作已成功完成,并带有结果值。
  • 已拒绝(rejected):表示操作已失败,并带有错误信息。

Promise 的实现

为了更好地理解 Promise 的工作原理,我们不妨自己动手实现一个简化版的 Promise。首先,我们需要定义一个构造函数:

function Promise(executor) {
  this.state = 'pending';
  this.result = undefined;
  this.onFulfilledCallbacks = [];
  this.onRejectedCallbacks = [];

  const resolve = (value) => {
    if (this.state !== 'pending') return;

    this.state = 'fulfilled';
    this.result = value;
    this.onFulfilledCallbacks.forEach((callback) => callback(value));
  };

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

    this.state = 'rejected';
    this.result = error;
    this.onRejectedCallbacks.forEach((callback) => callback(error));
  };

  executor(resolve, reject);
}

在构造函数中,我们初始化了 Promise 的状态、结果值和回调函数数组。然后,我们定义了 resolvereject 方法,它们用于改变 Promise 的状态和结果值,并调用相应的回调函数。

接下来,我们需要定义 then 方法,它允许我们在 Promise 完成或失败时执行回调函数:

Promise.prototype.then = function(onFulfilled, onRejected) {
  return new Promise((resolve, reject) => {
    if (this.state === 'fulfilled') {
      setTimeout(() => {
        try {
          const result = onFulfilled(this.result);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      }, 0);
    } else if (this.state === 'rejected') {
      setTimeout(() => {
        try {
          const result = onRejected(this.result);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      }, 0);
    } else {
      this.onFulfilledCallbacks.push(() => {
        setTimeout(() => {
          try {
            const result = onFulfilled(this.result);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        }, 0);
      });

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

then 方法中,我们首先检查 Promise 的当前状态。如果它是已完成的,我们就立即执行 onFulfilled 回调函数,并将结果值传递给新的 Promise。如果它是已拒绝的,我们就立即执行 onRejected 回调函数,并将错误信息传递给新的 Promise。如果它是待定的,我们就将 onFulfilledonRejected 回调函数添加到相应的数组中,以便在 Promise 完成或失败时执行它们。

最后,我们需要定义 catch 方法,它允许我们在 Promise 失败时执行回调函数:

Promise.prototype.catch = function(onRejected) {
  return this.then(null, onRejected);
};

catch 方法实际上只是 then 方法的语法糖,它允许我们更简洁地处理 Promise 的失败情况。

结语

通过自己实现一个简化版的 Promise,我们对 Promise 的内部机制有了更深入的了解。这将帮助我们在实际开发中更有效地使用 Promise,编写出更加健壮、可维护的代码。