实现自定义的 Promise 实例

阅读时长 10 分钟读完

Promise 是 JS 常用的异步编程解决方案之一,它可以让代码更加优雅地处理异步操作,避免了回调地狱。本文将介绍如何实现自定义的 Promise 实例。

Promise 基本原理

Promise 有三种状态:Pending(进行中)、Fulfilled(已成功)和Rejected(已失败)。当 Promise 实例的状态从 Pending 转变为 Fulfilled 或者 Rejected 时,便进入终态。终态状态不可改变。

Promise 实例可以接受一个函数作为参数,该函数包含两个参数 resolve 和 reject。当异步操作成功时,需要调用 resolve 函数,把异步操作的结果作为参数传递给 resolve 函数;当异步操作失败时,需要调用 reject 函数,把异步操作的错误作为参数传递给 reject 函数。

例如:

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

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

在上面的代码中,Promise 实例接受一个参数函数,该函数包含一个定时器,定时器回调函数中调用 resolve 函数,把字符串 'Hello World!' 作为参数传递给 resolve 函数,表示异步操作成功。promise.then() 方法可以接收 resolve 函数传递过来的参数,打印出 'Hello World!'。如果异步操作失败,则会执行 catch() 方法中的回调函数。

自定义 Promise 实例

我们知道 Promise 是 ES6 中新增的语法,旧版浏览器不支持 Promise。为了兼容旧版浏览器,并深入理解 Promise 原理,让我们来实现自定义的 Promise 实例。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

上述代码中,首先定义了 Promise 类的构造函数,初始化 Promise 实例的状态、存储 resolve 函数和 reject 函数的参数、存储 then 和 catch 回调函数的数组。

然后定义了 then 方法和 catch 方法,处理 Promise 实例的状态以及回调函数的参数,返回一个新的 Promise 实例。resolvePromise 方法是用来处理 then 和 catch 回调函数的返回值。在将返回值传递给下一个 Promise 实例之前,需要先判断值是不是 Promise 实例,如果是则需要等待返回的 Promise 实例状态变更之后再继续传递下去。

示例

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

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

在这个例子中,我们创建了一个 MyPromise 实例,定时器回调函数中调用了 resolve 函数,把字符串 'Hello World!' 作为参数传递给 resolve 函数,表示异步操作成功。第一个 then 方法会打印出 'Hello World!',并返回一个新的 MyPromise 实例,在回调函数中设置了定时器,回调函数中调用了 resolve 函数,把字符串 'Hello World Again!' 作为参数传递给 resolve 函数,表示异步操作成功。第二个 then 方法会打印出 'Hello World Again!',catch 方法没有执行。如果异步操作失败,则会执行 catch 方法中的回调函数。

总结

通过自定义 Promise 实例,我们深入理解了 Promise 原理,并获得了进一步的学习和指导意义。当然,自定义的 Promise 实例并不适用于生产环境,因为它没有 Promise 的所有功能和可靠性,但是它能够帮助我们更深入地理解 Promise 实例的工作原理,掌握 Promise 实例的使用技巧,从而更好地进行异步编程。

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

纠错
反馈