Promise 源码学习笔记

阅读时长 12 分钟读完

前言

Promise 是 ES6 新增的一种异步编程解决方案,旨在解决回调地狱的问题。Promise 可以视为一种带有状态的函数容器,可以根据成功或失败的状态来执行不同的操作。在使用 Promise 时,我们可以以链式调用的方式来处理异步操作,而不必嵌套多层回调函数。

本篇文章主要介绍 Promise 的实现原理,通过学习 Promise 的源码,可以帮助我们更好地理解 Promise 的内部机制,从而更加熟练地使用 Promise。

内部实现

首先,让我们来看一下 Promise 的基本用法:

-- -------------------- ---- -------
--- ------- - --- ----------------- ------- -- -
  -- ----
  -- ----- --------------
  -- ----- -------------
---

------------------ -- -
  -- ----
-- ----- -- -
  -- ----
---

如上所示,Promise 是一个函数对象,并且接收一个函数参数,该函数会立即执行,并在异步操作完成后调用其参数,参数为成功或失败的回调函数。同时,Promise 对象还提供了 then 方法,用于处理异步操作的成功和失败情况。在使用 Promise 时,通常调用 then 方法来执行异步操作,并在 then 方法中处理异步操作的结果。

接下来,让我们看一下 Promise 的源码实现。

构造函数

Promise 对象的构造函数如下:

-- -------------------- ---- -------
-------- ----------------- -
  -- ------
  -- ------- -------- --- ----------- -
    ----- --- ------------------ -------- - - -------- - - -- --- - -----------
  -

  -- -------
  ----------------- - ---------- -- ------- ---
  ------------------ - ---------- -- ------- ----
  --------------------------- - --- -- ------- --------
  --------------------------- - --- -- ------- --------

  -- -- -------- --
  --- -
    --------------------------------- ------------------------
  - ----- ------- -
    -------------------
  -
-

Promise 构造函数接收一个参数 executor,该参数为一个函数,在 Promise 对象实例化时立即执行。在 executor 函数的内部,通过调用 this.resolve 和 this.reject 方法来修改 Promise 对象的状态和结果值。

在 Promise 对象实例化时,会初始化实例对象中的四个属性:promiseState、promiseResult、promiseFulfilReactions 和 promiseRejectReactions。

promiseState 表示 Promise 对象的状态,初始值为 'pending',表示 Promise 对象尚未完成异步操作。

promiseResult 表示 Promise 对象的结果值,初始值为 undefined,表示 Promise 对象尚未完成异步操作。

promiseFulfilReactions 和 promiseRejectReactions 分别为 Promise 对象的成功回调函数和失败回调函数。当 Promise 对象的状态发生变化时,会根据变化的状态调用对应的回调函数。

resolve 和 reject 方法

在 Promise 构造函数中,我们调用 this.resolve 和 this.reject 方法来修改 Promise 对象的状态和结果值,这两个方法定义如下:

-- -------------------- ---- -------
------------------------- - --------------- -
  -- ------------------ --- ---------- -------
  ----------------- - ------------
  ------------------ - ------
  -------------------------------------------- -- -----------------
  --------------------------- - ---
  --------------------------- - ---
--

------------------------ - --------------- -
  -- ------------------ --- ---------- -------
  ----------------- - -----------
  ------------------ - ------
  -------------------------------------------- -- -----------------
  --------------------------- - ---
  --------------------------- - ---
--

resolve 方法用于修改 Promise 对象的状态为成功状态,并传递成功的结果值。在调用 resolve 方法时,首先检查 Promise 对象的状态是否为 'pending',如果不是,则直接退出。然后,将 Promise 对象的状态修改为 'fulfilled',并将成功的结果值保存到 promiseResult 属性中。接着,遍历 promiseFulfilReactions 数组,并逐一调用其中的回调函数,传递成功的结果值。最后,清空 promiseFulfilReactions 和 promiseRejectReactions 数组。

reject 方法用于修改 Promise 对象的状态为失败状态,并传递失败的结果值。与 resolve 方法类似,reject 方法首先检查 Promise 对象的状态是否为 'pending',如果不是,则直接退出。然后,将 Promise 对象的状态修改为 'rejected',并将失败的结果值保存到 promiseResult 属性中。接着,遍历 promiseRejectReactions 数组,并逐一调用其中的回调函数,传递失败的结果值。最后,清空 promiseFulfilReactions 和 promiseRejectReactions 数组。

then 方法

Promise 对象的 then 方法主要用于处理 Promise 对象的成功和失败情况。then 方法定义如下:

-- -------------------- ---- -------
---------------------- - --------------------- ----------- -
  -- ---- ------- --
  --- ------- - --- ----------------- ------- -- -
    ------ ------------------- -
      ---- ----------
        -- -----------------
        ---------------------------------------- -- -
          --- -
            --- - - -------------------
            ---------------------------- -- -------- --------
          - ----- ------- -
            --------------
          -
        ---
        ---------------------------------------- -- -
          --- -
            --- - - ------------------
            ---------------------------- -- -------- --------
          - ----- ------- -
            --------------
          -
        ---
        ------
      ---- ------------
        --- -
          --- - - --------------------------------
          ---------------------------- -- -------- --------
        - ----- ------- -
          --------------
        -
        ------
      ---- -----------
        --- -
          --- - - -------------------------------
          ---------------------------- -- -------- --------
        - ----- ------- -
          --------------
        -
        ------
    -
  ---
  ------ --------
--

then 方法接收两个参数,分别为成功回调函数和失败回调函数。在 then 方法内部,我们首先创建一个新的 Promise 对象。接着,根据当前 Promise 对象的状态,分别执行不同的逻辑。

当当前 Promise 对象的状态为 'pending' 时,我们将成功和失败的回调函数分别添加到 promiseFulfilReactions 和 promiseRejectReactions 数组中。这样,当 Promise 对象的状态发生变化时,会根据变化后的状态调用相应的回调函数,并传递相应的结果值。

当当前 Promise 对象的状态为 'fulfilled' 时,我们直接执行成功的回调函数,并传递当前 Promise 对象保存的成功结果值。

当当前 Promise 对象的状态为 'rejected' 时,我们直接执行失败的回调函数,并传递当前 Promise 对象保存的失败结果值。

在执行成功或失败回调函数时,我们还需要根据回调函数的返回值来决定新的 Promise 对象的状态和结果值。具体实现逻辑在 resolvePromise 方法中,该方法定义如下:

-- -------------------- ---- -------
-------------------------------- - ----------------- -- -------- ------- -
  -- -------- --- -- -
    ---------- -------------- ------- --- --- ------ ----- --- --- --------
    -------
  -

  -- -- ---------- -------- -
    -- -------------- --- ---------- -
      -------- -- -
        ---------------------------- -- -------- --------
      -- ----- -- -
        --------------
      ---
    - ---- -
      --------------- --------
    -
    -------
  -

  -- -- --- ---- -- ------- - --- -------- -- ------ - --- ------------ -
    --- ------ - ------
    --- -
      --- ---- - -------
      -- ------- ---- --- ----------- -
        ------------ - -- -
          -- -------- -------
          ------ - -----
          ---------------------------- -- -------- --------
        -- ----- -- -
          -- -------- -------
          ------ - -----
          --------------
        ---
      - ---- -
        -----------
      -
    - ----- ------- -
      -- -------- -------
      ------ - -----
      --------------
    -
    -------
  -

  -----------
--

resolvePromise 方法接收四个参数,分别为新的 Promise 对象、回调函数的返回值 x、resolve 方法和 reject 方法。

当回调函数的返回值 x 和新的 Promise 对象 promise 相同时,我们将新 Promise 对象的状态修改为失败状态,并传递错误信息 'The promise and the return value are the same'。

当回调函数的返回值 x 是 Promise 对象时,我们需要判断 Promise 对象的状态,如果为 'pending',则需要等待 Promise 对象状态的改变,并递归调用 resolvePromise 方法;如果为 'fulfilled' 或 'rejected',则直接调用 resolve 或 reject 方法。

当回调函数的返回值 x 是对象或函数时,我们需要判断其是否声明了 then 方法。如果声明了,则调用 then 方法,并在 then 方法中递归调用 resolvePromise 方法;如果未声明,则直接调用 resolve 方法。

当回调函数的返回值 x 是其他值时,直接调用 resolve 方法。

catch 方法

在 Promise 对象操作过程中,我们可能会希望在出现错误时做出相应的处理。为此,ES6 提供了 catch 方法,用于处理 Promise 对象的错误情况。catch 方法等价于 then 方法的第二个参数,也就是失败回调函数。catch 方法定义如下:

在 catch 方法中,我们需要调用 then 方法,并将成功回调函数设置为 null,失败回调函数设置为 onRejected。

总结

通过以上的源码学习,我们可以深入了解 Promise 内部的实现原理,从而更加熟悉 Promise 的使用方法。可以看到,Promise 主要通过构造函数、resolve 方法、reject 方法、then 方法、catch 方法等模块来实现 Promise 对象的状态管理、异步操作处理。

同时,我们还需要注意 Promise 对象的 then 方法和 resolvePromise 方法中的逻辑实现,要根据不同的状态和返回值,做出相应的错误处理和状态转换,使其能真正达到异步操作的效果。

最后,希望本文能对大家学习 Promise 有所帮助,同时也希望读者能够认真学习,加深对 Promise 的理解,为自己的编程技能提高贡献一份力量。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64599ea5968c7c53b0bbb5e6

纠错
反馈