返回

Promise 源码剖析:揭秘 then 链式调用和核心实现原理

前端

目录



前言

在现代 JavaScript 开发中,Promise 已经成为异步编程的标配。它提供了优雅的方式来处理异步操作,使代码更加清晰易读。本文将带你深入剖析 Promise 的核心实现原理,了解 then 链式调用的工作方式以及 finally 和 catch 方法的实现。通过对 Promise 源码的细致解读,你将掌握异步编程的精髓,并能写出更加健壮和可维护的代码。

目录

Promise 的基本原理

Promise 是一个 JavaScript 对象,它代表一个异步操作的最终完成或失败的结果。Promise 可以处于三种状态之一:

  • 待定(Pending):初始状态,表示异步操作尚未完成。
  • 已完成(Fulfilled):异步操作已成功完成,并带有结果值。
  • 已拒绝(Rejected):异步操作已失败,并带有错误原因。

Promise 提供了 then 方法,允许你为 Promise 指定回调函数,以便在 Promise 完成时执行。then 方法接收两个参数:

  • 成功回调函数:当 Promise 完成时执行,并接收 Promise 的结果值作为参数。
  • 失败回调函数:当 Promise 失败时执行,并接收 Promise 的错误原因作为参数。

then 链式调用

then 链式调用是指连续调用 then 方法,以便在 Promise 完成时执行一系列操作。这种技术非常有用,因为它可以让你将多个异步操作连接起来,并按顺序执行。

then 链式调用的工作原理如下:

  1. 当你调用 then 方法时,JavaScript 引擎会创建一个新的 Promise 对象。
  2. 新 Promise 对象的状态与原始 Promise 对象的状态相关联。
  3. 如果原始 Promise 对象已完成,则新 Promise 对象的状态也为已完成,并将结果值传递给成功回调函数。
  4. 如果原始 Promise 对象已拒绝,则新 Promise 对象的状态也为已拒绝,并将错误原因传递给失败回调函数。
  5. 你可以在 then 链式调用中继续调用 then 方法,以执行更多操作。

finally 和 catch 方法

finally 方法允许你为 Promise 指定一个回调函数,以便在 Promise 完成或失败时执行。finally 方法的回调函数不接收任何参数,并且总是会被执行,无论 Promise 的状态如何。

catch 方法允许你为 Promise 指定一个回调函数,以便在 Promise 失败时执行。catch 方法的回调函数接收一个参数,该参数是 Promise 的错误原因。

Promise 的实现

Promise 的实现相对简单,但它巧妙地利用了 JavaScript 的事件循环机制。Promise 的核心实现如下:

class Promise {
  constructor(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 = (reason) => {
      if (this.state !== 'pending') return;
      this.state = 'rejected';
      this.result = reason;
      this.onRejectedCallbacks.forEach((callback) => callback(reason));
    };

    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    return new Promise((resolve, reject) => {
      const handleFulfilled = (value) => {
        try {
          const result = onFulfilled ? onFulfilled(value) : value;
          resolve(result);
        } catch (error) {
          reject(error);
        }
      };

      const handleRejected = (reason) => {
        try {
          const result = onRejected ? onRejected(reason) : reason;
          resolve(result);
        } catch (error) {
          reject(error);
        }
      };

      if (this.state === 'pending') {
        this.onFulfilledCallbacks.push(handleFulfilled);
        this.onRejectedCallbacks.push(handleRejected);
      } else if (this.state === 'fulfilled') {
        setTimeout(() => {
          handleFulfilled(this.result);
        }, 0);
      } else if (this.state === 'rejected') {
        setTimeout(() => {
          handleRejected(this.result);
        }, 0);
      }
    });
  }

  catch(onRejected) {
    return this.then(undefined, onRejected);
  }

  finally(onFinally) {
    return this.then(
      (value) => {
        onFinally();
        return value;
      },
      (reason) => {
        onFinally();
        return reason;
      }
    );
  }
}

总结

Promise 是 JavaScript 中用于处理异步操作的强大工具。通过深入剖析 Promise 的核心实现原理,我们了解了 then 链式调用的工作方式,以及 finally 和 catch 方法的实现。掌握这些知识,你将能够编写出更加健壮和可维护的代码。