在 ECMAScript 2018 中手动实现 async/await

前言

在 JavaScript 中,异步编程一直都是一项棘手的任务。早期,我们通常使用回调函数来处理异步操作,但这种方式很容易导致回调地狱,代码变得难以理解和维护。随着 Promise 和 async/await 的出现,异步编程变得更加容易和优雅了。

async/await 是 ECMAScript 2017 中引入的一个新的异步编程概念。它可以使异步代码看起来像同步代码一样,让异步编程变得更加易读和易维护。本文将介绍如何手动实现 async/await 这个概念,以便更好地理解和掌握它。

Promise 的回顾

在介绍 async/await 之前,我们需要先回顾一下 Promise。Promise 是一种表示异步操作的对象,它可以让我们更方便的处理异步代码。具体来说,Promise 包含三种状态:

  • pending: 初始状态,既不成功,也不失败
  • fulfilled: 表示操作成功完成
  • rejected: 表示操作失败

我们可以通过 then() 方法来处理 Promise 成功返回的结果,也可以在 catch() 方法中处理 Promise 失败时的结果。

例子:

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

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

async/await 的基础知识

在学习 async/await 之前,需要先了解 Promise 和一些基本的 JavaScript 概念。async/await 只是 Promise 的语法糖,因此理解 Promise 对于学习 async/await 非常重要。

async/await 的本质

async/await 是一种基于 Promise 的异步编程方式。

async/await 关键字只是一个语法糖,实际上是将 Promise 的 then() 和 catch() 方法进行了封装。async 函数返回一个 Promise 对象,我们只需要使用 await 关键字来等待 Promise 的结果,就可以实现异步代码的同步执行。

async/await 的真正作用是改变异步代码的执行顺序,它可以使异步代码看起来像同步代码一样。

async 函数

async 函数是一个返回 Promise 的异步函数。这个函数声明会返回一个 AsyncFunction 对象。

async 函数可以包含多个 await 表达式,await 表达式会暂停整个 async 函数的执行,直到等待的 Promise 对象状态改变并返回结果。

例子:

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

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

await 表达式

await 表达式只能出现在 async 函数中。它的作用是等待一个 Promise 对象的结果,然后返回该结果。

如果 await 关键字后的表达式不是 Promise 的话,它会被转换为一个立即已解决的 Promise,并返回它的结果。

例子:

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

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

----------

如果 fetchData() 方法返回的结果不是一个 Promise,可以这样修改:

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

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

----------

手动实现 async/await

现在我们已经了解了 async/await 的原理,接下来我们将手动实现这个功能。我们将创建一个 AsyncFunction 类,类中包含了 async/await 的逻辑。

我们可以使用 Promise 和 Generator 来手动实现 async/await,但这种实现方式很复杂,且很难理解。因此,我们将使用 ES6 的箭头函数来实现。

AsyncFunction 类的实现

首先,我们需要定义一个 AsyncFunction 的类,这个类的作用是返回一个 Promise。

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

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

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

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

await 表达式的实现

接下来,我们需要定义一个 await() 函数,这个函数的作用是将 promise 的结果返回给 generator。

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

async 函数的实现

最后,我们将使用 AsyncFunction 类和 await() 函数来重写 async 函数。我们可以使用箭头函数和类的实例方法来实现这个过程。

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

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

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

-------

输出:

-----
---

总结

本文介绍了 async/await 的基本知识,并手动实现了 async/await 的功能。通过手动实现 async/await,我们可以更好地了解这个概念,并掌握 Promise 和 JavaScript 异步编程的基本知识。

在实际的代码编写中,我们仍然建议使用标准的 async/await 语法,而不是手动实现的方式。通过使用 async/await,我们可以减少代码重复、提高代码的可读性和可维护性。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/66530432d3423812e4789d25