ES8 的优美语法 Async / Await:Promise 的进化版?

阅读时长 8 分钟读完

ES8 是 ECMAScript 的第八个版本,也是最新的一个版本。在 ES8 中,加入了 Async / Await 这种语法糖,使得异步编程更加简单、易懂。本文将介绍 Async / Await 的使用方法、优美语法背后的实现原理,以及与 Promise 的异同之处。

1. Async / Await 的使用方法

Async / Await 是基于 Promise 实现的语法糖,用于解决 Promise 中回调嵌套过多的问题。它在语法上使用起来更加简洁易懂,代码可读性更强。下面是一个简单的例子:

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

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

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

以上的代码中,我们定义了一个 delay 函数,它返回一个 Promise,并在一定时间后 resolve。我们接着定义了一个 async 函数 asyncDelay,其中使用了 await 关键字来等待 delay 函数的结果。最后的 asyncDelay() 调用会输出以下结果:

可以看出,asyncDelay 函数执行时会首先输出 'before delay',然后等待 1 秒钟,最后输出 'after delay'。

在实际应用中,Async / Await 很容易与其他操作一起使用,如网络请求、数据库操作等。接下来,我们将详细介绍 Async / Await 的实现原理。

2. Async / Await 的实现原理

在前面的例子中,我们已经使用了 await 关键字来等待 Promise 对象的结果。那么,await 关键字是如何实现等待的呢?

在普通函数或类中使用 await 关键字会报错,但在 async 函数(也称异步函数)中使用它可以起到类似暂停的效果,使得代码在等待异步操作完成后再行执行。在实际执行时,async 函数的返回值是一个 Promise 对象。

换句话说,Async / Await 执行的本质还是 Promise。当我们需要等待一些异步操作完成时,可以使用 await,但必须在 async 函数中使用。async 函数将异步操作封装成一个 Promise 对象,同时还可以像普通函数一样传递参数。这样一来,我们就不必再使用 Promise 的回调嵌套,大大简化了异步编程的复杂度。

下面我们来看一个实现 Async / Await 的伪代码:

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

以上的代码中,我们定义了一个 asyncToGenerator 函数,它接受一个 generator 函数作为参数,并返回一个新函数。在该新函数中,我们获取到了 generator 函数的迭代器对象 gen,然后定义了 next 函数。

在 next 函数中,我们首先获取下一个 yield 的结果。如果迭代器已经结束,则返回一个 Promise 对象并解析出结果值。如果迭代器还未结束,则使用 Promise.resolve 将该值转换成一个 Promise 对象,并将其作为参数传递给 next 函数继续进行迭代。如果出现异常,则使用 gen.throw 抛出。

以上是 Async / Await 的实现原理的简单解释,接下来我们将和 Promise 做一个对比,看一下二者在使用上的异同之处。

3. Async / Await 与 Promise 的异同

异步编程在 JavaScript 中是一项很重要的功能。在 ES6 之前,Promise 是比较好的异步解决方案,但在实际使用过程中,仍然存在一些回调嵌套及复杂性的问题。因此,在 ES8 中,Async / Await 语法糖被引入,以简化异步编程。

与 Promise 相比,Async / Await 的语法更加优雅,使得异步代码更加易读、易写。以下是 Async / Await 和 Promise 的对比:

3.1 使用方式

Promise 通过两个方法 then() 和 catch() 来处理异步操作:

而 Async / Await 则通过 async 和 await 关键字来改变异步编码的方式:

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

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

可以看出,Async / Await 更加符合人的思维方式,代码也更加优雅。

3.2 错误处理

在 Promise 中,我们可以使用 catch() 方法来处理异常:

而在 Async / Await 中,我们可以使用 try..catch 捕获异常:

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

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

3.3 并发请求

在 Promise 中,我们可以使用 Promise.all() 方法并发执行多个异步操作,并在所有异步操作完成后返回一个数组:

而在 Async / Await 中,我们可以使用 Promise.all() 方法并发执行多个异步操作,并在所有异步操作完成后返回一个数组:

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

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

以上就是 Async / Await 和 Promise 的使用方法及异同之处的详细介绍。

4. 总结

Async / Await 是在 ES8 中引入的一种优美的异步编程方式,它基于 Promise 实现,使得异步操作更加易读、易写。在使用 Async / Await 时,我们需要将异步操作封装成一个 Promise 对象,并在 async 函数中使用 await 关键字等待其结果。

与 Promise 相比,Async / Await 的代码更加优雅、易读,使得异步编程更加简单。同时,Async / Await 可以通过 try..catch 捕获异常、使用 Promise.all() 并发执行多个异步操作,更加灵活实用。

虽然 Async / Await 给了我们更多的便捷,但在实际开发过程中,我们仍需要将它和 Promise 结合使用,以避免一些因异步编程带来的问题。

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

纠错
反馈

纠错反馈

程序员教程

精选优质教程,助你快速提升技术实力

程序员面试题库

海量优质面试题,助你轻松应对技术面试