JS 中手写 Promise 的实现方式

阅读时长 8 分钟读完

概述

Promise 是 JavaScript 中非常重要的一种异步编程方式,在 Node.js 和浏览器端都有广泛应用。它可以更好地处理异步操作,避免了回调地狱等问题,从而使代码更加优雅可读。

在学习 Promise 过程中,你可能会好奇 Promise 究竟是如何实现的,其背后的原理是什么。本文将带你深入浅出地剖析 JavaScript 中 Promise 的实现方式,以及手写 Promise 的实现思路和示例代码,帮助你更好地理解 Promise。

Promise 的基本概念

在深入分析 Promise 的实现方式前,我们先了解一下 Promise 的一些基本概念。

Promise 是 JavaScript 中表示异步操作的对象,它可以在异步操作完成后返回结果、错误等信息。Promise 有三个状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。

  • pending:表示异步操作正在进行中,此时 Promise 的结果是未知的;
  • fulfilled:表示异步操作已成功,此时 Promise 的结果已经可以被访问;
  • rejected:表示异步操作已失败,此时 Promise 的结果也已经可以被访问。

Promise 对象被创建后,可以为其绑定resolvereject回调函数,用来处理异步操作成功或失败后的结果。当异步操作成功后,调用resolve函数来返回异步操作结果;当异步操作失败时,调用reject函数来返回异步操作失败的原因。在异步操作成功或者失败后,Promise 的状态会相应地从pending变成已成功或已失败。

手写 Promise 的实现方式

实现一个 Promise 需要定义一个构造函数,并为其原型添加一些方法。构造函数中需要接收一个参数excutor,该参数是一个函数,用来处理异步操作成功或失败后的结果。该函数接收两个参数:resolvereject,分别表示异步操作成功和失败后的处理函数。

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

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

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

  -- --------
  --- -
    ----------------- --------
  -
  ----- ----- -
    ------------
  -
-
展开代码

构造函数中定义了_status_value_reason三个私有变量,用来存储 Promise 的状态、异步操作成功后的值和异步操作失败的原因。

定义了resolvereject两个私有函数用来处理异步操作的成功或失败后的结果。在异步操作成功或失败时,如果当前 Promise 的状态是pending,则将 Promise 的状态相应地改变为已成功或已失败,并存储异步操作成功或失败的结果。

在构造函数末尾,调用了传入的executor函数,并传入resolvereject函数,用来执行异步操作。如果在执行异步操作时发生异常,则直接将异常作为异步操作的失败原因并调用reject函数。

接下来,我们为 Promise 的原型添加一些必要的方法。

Promise.prototype.then

then方法是 Promise 最基本的方法,它接收两个参数:onFulfilledonRejected,分别表示异步操作成功或失败后的回调函数。

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

  ------ -------------- -
    ---- ----------
      ----- -------- - -----
      ------ --- ------------------- ------- -- -
        -------------------------------- -- -
          --- -
            ----- - - -----------------------------
            ------------------------ -- -------- --------
          -
          ----- ----- -
            ------------
          -
        ---
        ------------------------------- -- -
          --- -
            ----- - - -----------------------------
            ------------------------ -- -------- --------
          -
          ----- ----- -
            ------------
          -
        ---
      ---
    ---- ------------
      ----- -------- - --- ------------------- ------- -- -
        --- -
          ----- - - -------------------------
          ------------------------ -- -------- --------
        -
        ----- ----- -
          ------------
        -
      ---
      ------ ---------
    ---- -----------
      ----- -------- - --- ------------------- ------- -- -
        --- -
          ----- - - -------------------------
          ------------------------ -- -------- --------
        -
        ----- ----- -
          ------------
        -
      ---
      ------ ---------
  -
--
展开代码

then方法中,我们首先对onFulfilledonRejected函数进行有效性检查,如果传入的回调不是函数,则创建一个默认的回调函数。

接着,根据当前 Promise 的状态,分别处理异步操作成功或失败后的回调函数。如果当前状态为pending,则将回调函数添加到对应的队列中。如果当前状态为fulfilledrejected,则可以直接执行回调函数。

最后,我们需要在promise中实现一个resolvePromise函数来处理回调函数的返回值。我们需要在函数中对返回值进行类型判断。如果返回值是一个 Promise,则需要等待该 Promise 也被执行完毕,再将其状态和结果传递给下一个回调函数。如果返回值是一个普通值,则直接将其传递给下一个回调函数。

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

  -- -- --- ---- -- ------- - --- ---------- -- ------ - --- ---------- -
    --- ------ - ------
    --- -
      ----- ---- - -------
      -- ------- ---- --- ----------- -
        ------------ - -- -
          -- -------- -------
          ------ - -----
          ----------------------- -- -------- --------
        -- - -- -
          -- -------- -------
          ------ - -----
          ----------
        --
      - ---- -
        -----------
      -
    -
    ----- ----- -
      -- -------- -------
      ------ - -----
      ------------
    -
  - ---- -
    -----------
  -
-
展开代码

结语

通过手写 Promise 的实现方式,我们更深入地了解了 Promise 的底层实现原理。对于理解异步编程、优化代码结构等方面,掌握 Promise 的实现方式是非常有帮助的。

当然,上面的代码只是 Promise 的一种基本实现方式,我们还可以根据业务需求对 Promise 的实现进行扩展。希望大家能够在学习 Promise 中更多地去探索、思考和实践。

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

纠错
反馈

纠错反馈