使用 TypeScript 实现一个 Promise

阅读时长 8 分钟读完

引言

Promise 是 JavaScript 中很常用的一个异步编程解决方案,它解决了回调地狱的问题,可以更加优雅地处理异步操作。在 TypeScript 中,我们也常常会使用 Promise 来处理异步请求。在本文中,我们将使用 TypeScript 来实现一个 Promise,以了解 Promise 的实现原理和带来更丰富的使用场景。

Promise 的基本原理

Promise 有三个状态:pendingfulfilledrejected,分别代表异步操作的进行中、已成功完成和已失败完成。一个 Promise 初始状态为 pending,当异步操作成功后,状态变为 fulfilled,并携带一个返回值;当异步操作失败后,状态变为 rejected,并携带一个错误原因。

我们可以使用 then 方法来注册 Promise 状态的回调函数,当异步操作成功后,执行 onFulfilled 回调函数,当异步操作失败后,执行 onRejected 回调函数。如果我们在使用 then 方法时,Promise 的状态尚未确定,则当前的 then 方法会先被放入 “待处理” 队列中,等到 Promise 状态确定后再执行。

TypeScript 实现一个 Promise

1. 定义一个 Promise 类

我们可以从最简单的形式开始定义一个 Promise 类,首先我们定义三个状态和两个回调函数。

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

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

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

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

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

在定义类时,我们需要定义类的类型(type)和类的属性和方法。我们使用 type 定义了 PromiseStatus 类型,表示 Promise 的三种状态,也方便后续代码调用。

定义 Promise 类,它有三个属性:

  • status:表示 Promise 的状态,初始化为 pending
  • result:表示异步操作返回的结果,如果没有结果,则为 undefined
  • errReason:表示异步操作失败的原因。

另外,定义了两个回调函数:

  • onFulfilled:表示异步操作成功后的回调函数。
  • onRejected:表示异步操作失败后的回调函数。

Promise 类的构造函数中,我们需要传入一个参数 executor,这个函数会传入两个函数参数:resolvereject。当异步操作成功时,调用 resolve(result) 方法;当异步操作失败时,调用 reject(reason) 方法。

2. 实现 resolve 方法

当我们使用 resolve(result) 方法时,Promise 的状态应该从 pending 变为 fulfilled,并执行 onFulfilled(result) 回调函数。如果我们在 resolve(result) 方法之前调用了 then(onFulfilled) 方法,则会将 onFulfilled 方法加入待处理队列中。

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

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

我们需要判断 Promise 的当前状态是否为 pending,如果不是,则不执行后续逻辑。如果当前状态为 pending,则修改状态为 fulfilled,并设置返回结果为 result。最后使用 setTimeout 来异步处理回调函数队列,以实现在异步执行完成后再执行回调函数。

3. 实现 reject 方法

resolve(result) 方法类似,当我们使用 reject(reason) 方法时,Promise 的状态应该从 pending 变为 rejected,并执行 onRejected(reason) 回调函数。如果我们在 reject(reason) 方法之前调用了 then(null, onRejected) 方法,则会将 onRejected 方法加入待处理队列中。

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

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

我们同样需要判断当前状态是否为 pending,并将状态修改为 rejected。最后异步处理回调函数队列。

4. 实现 then 方法

then(onFulfilled, onRejected) 方法是 Promise 中最基本的方法,我们可以使用它来注册 onFulfilledonRejected 两个回调函数。onFulfilled 函数和 onRejected 函数都是可选的,如果不需要,则使用 nullundefined 表示。

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

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

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

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

在 then 方法中,我们需要新建一个 Promise 对象,并将 onFulfilledonRejected 方法赋值。接着,判断当前 Promise 对象的状态分三种情况进行处理:

  • 当前状态为 pending 时,将 onFulfilledonRejected 方法放入待处理队列中,并返回新创建的 Promise 对象。
  • 当前状态为 fulfilled 时,直接执行 onFulfilled 方法,并返回新创建的 Promise 对象。
  • 当前状态为 rejected 时,直接执行 onRejected 方法,并返回新创建的 Promise 对象。

使用 TypeScript 实现一个 Promise 示例

我们可以使用上面实现的 Promise 类,来创建一个简单的例子。

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

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

在上述例子中,我们定义了一个异步方法 fetchData(),它返回一个 Promise 对象,并在 1 秒后调用 resolve("Hello World!") 方法来执行异步操作。最后我们通过 then 方法来获取 fetchData() 方法的返回值。

总结

在本文中,我们从 Promise 的基本原理开始讲解,然后使用 TypeScript 实现了一个 Promise 示例。使用 TypeScript 来实现 Promise 可以让我们更好的了解 Promise 的实现原理,并带来更丰富的使用场景。

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

纠错
反馈