【译】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的重要特性之一,也是目前社区里公认的优秀异步解 ...
随机推荐
- 记两道最近做的pwn题(ciscn_2019)
这两题为什么要记录呢,一个是我发现网上很多教程没写清楚(也可能是我太菜了),二是细节点很多,不同的大佬方式不太一样,有很多细节需要注意 ciscn_2019_es_2 这题是栈迁移的题,先上exp 1 ...
- Docker单机网络实战
前言 Docker系列文章: 此篇是Docker系列的第八篇,大家一定要按照我做的Demo都手敲一遍,印象会更加深刻的,加油! 为什么要学习Docker Docker基本概念 Docker镜像基本原理 ...
- LeetCode 895. Maximum Frequency Stack
题目链接:https://leetcode.com/problems/maximum-frequency-stack/ 题意:实现一种数据结构FreqStack,FreqStack需要实现两个功能: ...
- python+API接口测试框架设计(unittest)
1.测试框架简介 整个接口测试框架的设计图如下: basepage:存放的是公共的方法 common:存放的是自定义工具 data:存放的是公共动态数据,如BB.xls/ Id.md log:存放的是 ...
- PAT乙级:1092 最好吃的月饼 (20分)
PAT乙级:1092 最好吃的月饼 (20分) 题干 月饼是久负盛名的中国传统糕点之一,自唐朝以来,已经发展出几百品种. 若想评比出一种"最好吃"的月饼,那势必在吃货界引发一场腥风 ...
- 如何在cmd中运行.py文件
C:\Users\mf>cd C:\Program Files\Python36\ C:\Program Files\Python36>python const.py 切换到.py文件所在 ...
- P3209-平面图判定
平面图 平面图就是所有点的连边不相交的图.(当然是在你尽量想让它不相交的情况下).这一点可以大概理解成拓扑图的性质,即每连一条边就会将某个区域进行分割--很明显,如果两个点分别处在两个不可达的区域,它 ...
- 在Windows7/8/10 64位操作系统下安装并注册ocx控件
例如: 先网上下载一个MtbLine.ocx控件放入C:\Windows\SysWOW64\目录下 1.首先确保你的 Windows7 账户是管理员权限 2.下载MtbLine.ocx控件,网上可搜到 ...
- 手把手教你玩转HarmonyOS版地图应用开发
一.导读 7月31日,华为HarmonyOS开发者日将在杭州举行.为了方便更多开发者,高德开放平台地图SDK已在业内率先实现鸿蒙化迁移和重构,全面适配HarmonyOS并面向开发者免费发布.开发者可 ...
- vscode安装ESlint配置
先安装插件ESLint,后面在设置setting.json中配置加入代码: { "files.autoSave": "afterDelay", "ed ...