【译】JavaScript async / await:好的部分,陷阱和如何使用
async/await提供了一种使用同步样式代码异步访问资源的选项,而不会阻塞主线程。然而,使用它有点棘手。在本文中,我们将从不同的角度探讨async / await,并将展示如何正确有效地使用它们。
async / await的好处
async/await给我们带来的最重要的好处是同步编程风格。我们来看一个例子吧。
// async / await
async getBooksByAuthorWithAwait(authorId){
const books = await bookModel.fetchAll();
return books.filter(b => b.authorId === authorId);
}
// promise
getBooksByAuthorWithPromise(authorId){
return bookModel.fetchAll()。then(
books => books.filter(b => b.authorId === authorId));
}
很明显,async/await版本比承诺版本更容易理解。
另一个不太明显的好处是async关键字。它声明getBooksByAuthorWithAwait()函数返回值保证是一个promise,以便调用者可以调用getBooksByAuthorWithAwait().then(...)或await getBooksByAuthorWithAwait()安全。想想这个例子(不好的做法!):
getBooksByAuthorWithPromise(authorId){
if(!authorId){
return null;
}
return bookModel.fetchAll()。then(
books => books.filter(b => b.authorId === authorId));
}
在上面的代码中,getBooksByAuthorWithPromise可以返回一个promise(正常情况)或一个null值(例外情况),在这种情况下,调用者不能.then()安全地调用 。而通过async声明,就可以安全的用.then()调用了。
Async/await可能会产生误导
有些文章将async / await与Promise进行比较,并声称它是JavaScript异步编程演变的下一代,我不同意。Async / await是一种改进,但它只不过是一种语法糖,它不会完全改变我们的编程风格。
从本质上讲,异步函数仍然是承诺。在正确使用异步函数之前,您必须了解promises,更糟糕的是,大多数情况下您需要使用promises和异步函数。
考虑上面示例中的getBooksByAuthorWithAwait()和getBooksByAuthorWithPromises()函数。请注意,它们不仅在功能上相同,而且具有完全相同的界面!
getBooksByAuthorWithAwait()如果直接调用,这意味着将返回一个承诺。
嗯,这不一定是坏事。只有这个名字await让人感觉“哦,这可以将异步函数转换为同步函数”,这实际上是错误的。
Async/await陷阱
那么使用async/await时会出现什么错误?这是一些常见的。
太顺序了
虽然await可以使您的代码看起来像同步,但请记住它们仍然是异步的,必须注意避免过于顺序。
async getBooksAndAuthor(authorId){
const books = await bookModel.fetchAll();
const author = await authorModel.fetch(authorId);
return {
author,
books:books.filter(book => book.authorId === authorId),
};
}
此代码看起来逻辑正确。但这是错误的。
await bookModel.fetchAll()将等到fetchAll()返回。- 然后
await authorModel.fetch(authorId)将被执行。
请注意,authorModel.fetch(authorId)它不依赖于bookModel.fetchAll()的结果,实际上它们可以并行调用!但是,在这里使用了await,这两个调用变为顺序,并且总执行时间将比并行版本长得多。
这是正确的方法:
async getBooksAndAuthor(authorId){
const bookPromise = bookModel.fetchAll();
const authorPromise = authorModel.fetch(authorId);
const book = await bookPromise;
const author = await authorPromise;
return {
author,
books:books.filter(book => book.authorId === authorId),
};
}
或者更糟糕的是,如果你想逐个获取一个项目列表,你必须依赖Promise:
async getAuthors(authorIds){
// 错误,这将导致顺序调用
// const authors = _.map(
// authorIds,
// id => await authorModel.fetch(id));
// 正确
const promises = _.map(authorIds,id => authorModel.fetch(id));
const authors = await Promise.all(promises);
}
简而言之,您仍然需要异步考虑工作流,然后尝试await同步编写代码。在复杂的工作流程中,直接使用promises可能更容易。
【译】JavaScript async / await:好的部分,陷阱和如何使用的更多相关文章
- JavaScript async/await:优点、陷阱及如何使用
翻译练习 原博客地址:JavaScript async/await: The Good Part, Pitfalls and How to Use ES7中引进的async/await是对JavaSc ...
- JavaScript async/await 基础知识
async 作用: async函数返回一个 Promise对象,无论内部有没有await关键字. await 作用: await等待的是一个表达式,这个表达式的计算结果是 Promise 对象 或者是 ...
- 【译】Async/Await(一)——多任务
原文标题:Async/Await 原文链接:https://os.phil-opp.com/async-await/#multitasking 公众号: Rust 碎碎念 翻译 by: Praying ...
- 【译】Async/Await(二)——Futures
原文标题:Async/Await 原文链接:https://os.phil-opp.com/async-await/#multitasking 公众号: Rust 碎碎念 翻译 by: Praying ...
- 【译】Async/Await(三)——Aysnc/Await模式
原文标题:Async/Await 原文链接:https://os.phil-opp.com/async-await/#multitasking 公众号: Rust 碎碎念 翻译 by: Praying ...
- 【译】Async/Await(四)—— Pinning
原文标题:Async/Await 原文链接:https://os.phil-opp.com/async-await/#multitasking 公众号: Rust 碎碎念 翻译 by: Praying ...
- 【译】Async/Await(五)—— Executors and Wakers
原文标题:Async/Await 原文链接:https://os.phil-opp.com/async-await/#multitasking 公众号: Rust 碎碎念 翻译 by: Praying ...
- JavaScript - async/await 基础示例
一个函数如果被 async 修饰,无论内部是否有 await的异步操作,都会返回一个 Promise 对象 demo 1 async function basicAsync() { let resul ...
- 七 vue学习 async/await
1: javaScript async/await: 调用async函数的时候,是异步的,函数后面的代码继续执行.! async / await是ES7的重要特性之一,也是目前社区里公认的优秀异步解 ...
随机推荐
- [Kong] basic-auth基本认证及ACL鉴权
目录 basic-auth 1. Route上启用插件 2. 创建一个Consumer 3. 为Consumer创建凭证 4. 验证凭证 ACL 用户鉴权 1. 在route上启用ACL鉴权插件 2. ...
- ms17-010 永恒之蓝漏洞复现(CVE-2017-0143)
0x01 首先对目标机的开放端口进行探测,我们可以使用探测神器nmap 发现开放的445端口,然后进行下一步的ms17-010的漏洞验证 0x02 打开MSF美少妇神器,用search命令搜索ms17 ...
- SpringBoot | 2.1 SpringBoot自动装配原理
@ 目录 前言 1. 引入配置文件与配置绑定 @ImportResource @ConfigurationProperties 1.1 @ConfigurationProperties + @Enab ...
- Hive——元数据表含义
Hive--元数据表含义 1.VERSION -- 查询版本信息 Field Type Comment VER_ID bigint(20) ID主键 SCHEMA_VERSION va ...
- IO编程之对象序列化
对象序列化的目标是将对象保存在磁盘中或者允许在网络中直接传输对象.对象序列化机制循序把内存中的java对象转换成平台无关的二进制流,从而允许把这种二进制流持久的保存在磁盘上,通过网络将这种二进制流传输 ...
- mybatis-5-关联查询
外键查询 1.回忆外键约束 注意要在tbl_dept中添加外键 #添加外键约束 # 此处Employee为外键表,dept为主键表 # 删除Employee的数据不会影响dapt,而删除dept一定会 ...
- 【Uva1025 A Spy in the Metro】动态规划
题目描述 某城市地铁是线性的,有n(2≤n≤50)个车站,从左到右编号1~n.有M1辆列车从第1站开始往右开,还有M2辆列车从第n站开始往左开.列车在相邻站台间所需的运行时间是固定的,因为所有列车的运 ...
- IDEA如何导出war包
网上有很多关于IDEA导出war包的教程,然而很多照着一步步操作以后,war包并不能在对应目录中找到.参考网上一篇博文,发现其方法描述比较详细且经验证有效. 完整流程如下: 首先点击这里进入项目的配置 ...
- CSS样式实现表头和列固定
效果图:第一行和第一列固定 <!DOCTYPE html> <html lang="zh"> <head> <meta cha ...
- Python -- 值转换为字符串的两种机制
可以通过以下两个函数来使用这两种机制:一是通过str函数,它会把值转换为合理形式的字符串,以便用户可以理解:而repr会创建一个字符串,它以合法的Python表达式的形式来表示值.下面是一些例子: & ...