ES7 async/await 原理分析及实现方式

1. 引言

ES7 中引入了 async/await 关键字,它们是用来简化异步编程的新语法糖。对于有经验的 JavaScript 开发者们来说,async/await 很容易上手,看起来像同步编程。但实际上,async/await 是基于 Promise 的,正是因为 Promise 带来了异步编程的便利,才能让 async/await 在语法上更简化异步编程。

本文主要介绍 ES7 中的 async/await 的原理及应用实例,希望读者能够掌握其基本知识和应用技巧。

2. Async/Await 的原理分析

2.1 Promise 的特性

在了解 async/await 之前,需要先理解 Promise 的特性。Promise 是 JavaScript 异步编程的一种解决方案,它可以使得异步任务在特定的时间之后才会执行回调或返回结果。同时,Promise 还有以下三个特殊的状态:

  • pending 未完成状态,既不成功也不失败。
  • fulfilled 成功状态,Promise 对象已经执行成功,在处理结果时会调用 resolve() 去完成。
  • rejected 失败状态,Promise 对象执行失败,在处理结果时会调用 reject() 完成。

通常情况下,Promise 可以通过 .then().catch() 方法实现异步编程中的成功和失败的回调,如下所示:

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

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

2.2 Async/Await 的基本原理

Async/Await 是 Promise 的语法糖,它是通过将 Promise 进行封装来实现的,实现了一种更加简化异步编程的语法结构。

使用 Async/Await 需要标识函数是异步的,这可以通过在函数声明前加上 async 关键字来完成。在异步函数内部,可以使用 await 关键字来等待 Promise 对象完成。

await 表达式会暂停当前异步函数的执行,并等待 Promise 执行完毕。如果 Promise 被解决,就将解决结果作为 await 表达式的值返回。如果 Promise 被拒绝,await 抛出拒绝的值(就像在 Promise 原生回调中一样)。

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

在编写 Async/Await 的异步函数时,需要使用 try-catch 块来捕获可能的异常。在捕获异常时,如果 Promise 被 reject,就会抛出一个错误。

2.3 Async/Await 的优势

Async/Await 相对于 Promise 有以下几个优势:

  • 代码更加简洁、清晰,减少嵌套层次。
  • 更加易于理解,便于代码维护。
  • 可以通过 try-catch 来处理错误。
  • Async/Await 还可以和其他异步编程技巧如 Promise.all 和 Promise.race 结合使用。

3. Async/Await 的应用实例

3.1 异步读取文件内容

在 Node.js 中,可以使用 fs 模块来读取文件。使用异步的版本 fs.readFile() 可以通过 Async/Await 被简化为:

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

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

异步调用函数需要谨慎使用,如果文件很大,将会占用大量内存。在这种情况下,streaming 可能是更好的选择。

3.2 请求数据

使用 Async/Await 可以简化对 API 的请求,并将结果作为对象暴露给上层代码:

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

3.3 平行处理数据

假设要平行处理多个 API,可以使用一个并行方式,将结果一起返回,同时减少了等待每个请求的时间。

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

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

3.4 Async/Await 练习

以下代码块演示了如何使用 Async/Await 实现以下异步函数:

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

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

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

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

--------

此代码将按照以下顺序输出:2 秒后输出 Hello,接着 1 秒后输出 Goodbye

4. 结论

Async/Await 是 Promise 的语法糖,是一种更加简化异步编程的语法结构。在 ES7 中引入了该语法,它对于写异步代码非常方便、简洁易读。学习 Async/Await 以后,能让我们更加专注业务逻辑的处理,更加纯粹地开发代码。

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