[译]JavaScript async / await:好处、坑和正确用法

栏目: JavaScript · 发布时间: 6年前

内容简介:原文地址:ES7通过介绍

原文地址: JavaScript async/await: The Good Part, Pitfalls and How to Use

ES7通过介绍 async/await 使得JavaScript的异步编程实现了重大改进。它提供了一种使用同步代码样式异步访问 resoruces 的方式,而且不会阻塞主线程。然而,使用它有点棘手。在本文中,我们将从不同的角度探讨 async/await ,并将展示如何正确有效地使用它们。

async/await的好处

async/await 给我们带来的最重要的好处是同步编程风格。我们来看一个例子吧。

[译]JavaScript async / await:好处、坑和正确用法
很明显, async/await 版本比 promise 版本更容易理解。如果忽略 await

关键字,代码看起来就像任何其他同步语言,如Python。

好的一面不仅是可读性, async/await 有本地浏览器支持。截至今天,所有主流浏览器查看都完全支持异步功能。

[译]JavaScript async / await:好处、坑和正确用法

本机支持意味着您不必转换代码。更重要的是,它有助于调试。当您在函数入口设置断点并跳过 await 行时,您将看到调试器在 bookModel.fetchAll() 执行期间暂停一段时间,然后移动到下一 行 .filter !这比 promise 情况要容易得多,在 promise 情况下你必须在 .filter 行设置另一个断点 。

[译]JavaScript async / await:好处、坑和正确用法
另一个不太明显的好处是 async 关键字。它声明 getBooksByAuthorWithAwait() 函数返回值确保是一个 promise ,以便调用者可以安全调用 getBooksByAuthorWithAwait().then(...)await getBooksByAuthorWithAwait()

。看看下面的代码(不好的做法!):

[译]JavaScript async / await:好处、坑和正确用法
在上面的代码中, getBooksByAuthorWithPromise 可以返回一个 promise (正常情况)或一个 null 值(例外情况),在这种情况下,调用者不能安全地调用 .then() 。通过 async 声明,这种返回 null

的情况将不可能出现。

Async/await可能会产生误导

有些文章将 async/awaitPromise 进行比较,并声称它是JavaScript异步编程演变的下一代,我表示不同意。 Async/await 是一种改进,但它只不过是一种语法糖,它不会完全改变我们的编程风格。

从本质上讲, await 函数仍然是 promise 。在正确使用 await 函数之前,您必须了解 promises ,还有就是,大多数情况下您需要同时使用 promises 和异步函数。

考虑上面示例中的 getBooksByAuthorWithAwait()getBooksByAuthorWithPromises() 函数。请注意,它们不仅在功能上相同,而且具有完全相同的接口。

如果直接调用 getBooksByAuthorWithAwait() ,这意味着将返回一个 promise

嗯,这并不是坏事。只是 await 这个名称让人感觉“哦,这可以将异步函数转换为同步函数”,这实际上是错误的。

Async/await的坑

那么使用 async/await 时会出现什么错误?以下一些常见的情况。

太顺序了

虽然 await 可以使您的代码看起来像同步,但请记住它们仍然是异步的,必须注意避免过于顺序。

[译]JavaScript async / await:好处、坑和正确用法

此代码看起来逻辑正确。但这是错误的。

  1. await bookModel.fetchAll() 将等到 fetchAll() 返回。
  2. 然后 await authorModel.fetch(authorId) 将被调用。 请注意authorModel.fetch(authorId) 它不依赖于 bookModel.fetchAll() 的结果,实际上它们可以并行调用!但是,通过 await 在这里使用,这两个调用变为顺序,并且总执行时间将比并行版本长得多。

这是正确的方法:

[译]JavaScript async / await:好处、坑和正确用法
或者更糟糕的是,如果你想逐个获取一个列表的项,必须依赖 promise

[译]JavaScript async / await:好处、坑和正确用法
简单地说,您仍然需要异步考虑工作流,然后尝试同步编写代码 await 。在复杂的工作流程中,直接使用 promises

可能更容易。

错误处理

使用 promises ,异步函数有两个可能的返回值:已解析的值和被拒绝的值。我们可以 .then() 用于正常情况, .catch() 用于特殊情况。但是, async/await 错误处理可能会很棘手。

try…catch

最标准的(我推荐的)方法是使用 try...catch 语句。当一个 await 调用时,任何被拒绝的值都将作为异常抛出。这是一个例子:

[译]JavaScript async / await:好处、坑和正确用法
catch

的错误正是被拒绝的值。在我们发现异常后,有几种方法来处理它:

  1. 处理异常,并返回正常值。(不在 catch 块中使用任何 return 语句,这等同于使用 return undefined ,也是正常值。)
  2. 抛出它,如果你想让调用者处理它。可以直接抛出普通的错误对象 throw error ,这在 promise 链中允许使用 async getBooksByAuthorWithAwait() 函数(即仍然可以像这样调用它 getBooksByAuthorWithAwait().then(...).catch(error => ...) ); 或者可以使用 Error 对象包装错误,例如 throw new Error(error) ,当控制台中显示此错误时,将提供完整的堆栈跟踪。
  3. 拒绝它,就像 return Promise.reject(error) 。这相当于 throw error 不推荐。

使用try...catch的好处是:

  • 简单,传统。只要您有 Java 或C++等其他语言的经验,就不会有任何困难。
  • 如果不需要每步执行错误处理,仍然可以在一个 try...catch 块中包装多个 await 调用在一个位置处理错误。

这种方法也存在一个缺陷。由于 try...catch 将捕获块中的每个异常,因此将会捕获一些通常不会被 promises 捕获的异常。想想这个例子:

[译]JavaScript async / await:好处、坑和正确用法
运行此代码,您将在控制台中收到 ReferenceError: cb is not defined 错误。错误是由 console.log() 输出而不是JavaScript本身。有时这可能是致命的。如果 BookModel

被深深地包含在一系列函数调用中,并且其中一个调用吞噬了错误,那么找到这样的未定义错误将非常困难。

使函数返回两个值

另一种错误处理方式受 Go 语言的启发。它允许异步函数返回错误和结果。有关详细信息,请参阅此博客文章: How to write async await without try-catch blocks in Javascript

简言之,您可以使用这样的 await 函数:

[译]JavaScript async / await:好处、坑和正确用法

我个人不喜欢这种方法,因为它将Go风格带入JavaScript,感觉不自然,但在某些情况下,这可能非常有用。

使用.catch

我们将在这里介绍的最后一种方法是继续使用 .catch()

回想一下 await 的功能:它将等待 promise 完成其工作。再回想一下, promise.catch() 也将是一个 promise ,所以我们可以像这样编写错误处理:

[译]JavaScript async / await:好处、坑和正确用法

这种方法有两个小问题:

  1. 它是 promisesawait 函数的混合体。您仍然需要了解 promises 的工作原理。
  2. 错误处理在正常路径之前进行,这样不直观。

结论

ES7引入的关键字 async/await 肯定是对JavaScript异步编程的改进。它可以使代码更容易阅读和调试。然而,为了正确使用它们,必须完全理解 promise ,因为它们只不过是语法糖,而潜在的技术仍然是 promise


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java性能权威指南

Java性能权威指南

奥克斯 (Scott Oaks) / 柳飞、陆明刚、臧秀涛 / 人民邮电出版社 / 2016-3-1 / CNY 79.00

市面上介绍Java的书有很多,但专注于Java性能的并不多,能游刃有余地展示Java性能优化难点的更是凤毛麟角,本书即是其中之一。通过使用JVM和Java平台,以及Java语言和应用程序接口,本书详尽讲解了Java性能调优的相关知识,帮助读者深入理解Java平台性能的各个方面,最终使程序如虎添翼。 通过阅读本书,你可以: 运用四个基本原则最大程度地提升性能测试的效果 使用JDK中......一起来看看 《Java性能权威指南》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具