当前位置:网站首页>关于async\await 的理解和思考
关于async\await 的理解和思考
2022-08-10 14:43:00 【qzwzsl】
前段时间电脑坏了,一直没有继续更新博客,今天续上,就从号称最为优雅的异步处理方案async和await开始吧。
下面这是非常常见的代码:
(async () => {
const pizzaData = await getPizzaData(); // async call
const drinkData = await getDrinkData(); // async call
const chosenPizza = choosePizza(); // sync call
const chosenDrink = chooseDrink(); // sync call
await addPizzaToCart(chosenPizza); // async call
await addDrinkToCart(chosenDrink); // async call
orderItems(); // async call
})();await 语法本身没有问题,有时候可能是使用者用错了。当 pizzaData 与 drinkData 之间没有依赖时,顺序的 await 会最多让执行时间增加一倍的 getPizzaData 函数时间,因为 getPizzaData 与 getDrinkData 应该并行执行。
回到我们吐槽的回调地狱,虽然代码比较丑,带起码两行回调代码并不会带来阻塞。
看来语法的简化,带来了性能问题,而且直接影响到用户体验,是不是值得我们反思一下?
正确的做法应该是先同时执行函数,再 await 返回值,这样可以并行执行异步函数:
(async () => {
const pizzaPromise = selectPizza();
const drinkPromise = selectDrink();
await pizzaPromise;
await drinkPromise;
orderItems(); // async call
})();或者使用 Promise.all 可以让代码更可读:
(async () => {
Promise.all([selectPizza(), selectDrink()]).then(orderItems); // async call
})();思考:
仔细思考为什么 async/await 会被滥用,笔者认为是它的功能比较反直觉导致的。
首先 async/await 真的是语法糖,功能也仅是让代码写的舒服一些。先不看它的语法或者特性,仅从语法糖三个字,就能看出它一定是局限了某些能力。
举个例子,我们利用 html 标签封装了一个组件,带来了便利性的同时,其功能一定是 html 的子集。又比如,某个轮子哥觉得某个组件 api 太复杂,于是基于它封装了一个语法糖,我们多半可以认为这个便捷性是牺牲了部分功能换来的。
功能完整度与使用便利度一直是相互博弈的,很多框架思想的不同开源版本,几乎都是把功能完整度与便利度按照不同比例混合的结果。
那么回到 async/await 它的解决的问题是回调地狱带来的灾难:
a(() => {
b(() => {
c();
});
});
为了减少嵌套结构太多对大脑造成的冲击,async/await 决定这么写:
await a();
await b();
await c();虽然层级上一致了,但逻辑上还是嵌套关系,这不是另一个程度上增加了大脑负担吗?而且这个转换还是隐形的,所以许多时候,我们倾向于忽略它,所以造成了语法糖的滥用。
理解语法糖
虽然要正确理解 async/await 的真实效果比较反人类,但为了清爽的代码结构,以及防止写出低性能的代码,还是挺有必要认真理解 async/await 带来的改变。
首先 async/await 只能实现一部分回调支持的功能,也就是仅能方便应对层层嵌套的场景。其他场景,就要动一些脑子了。
比如两对回调:
a(() => {
b();
});
c(() => {
d();
});如果写成下面的方式,虽然一定能保证功能一致,但变成了最低效的执行方式:
await a();
await b();
await c();
await d();因为翻译成回调,就变成了:
a(() => {
b(() => {
c(() => {
d();
});
});
});然而我们发现,原始代码中,函数 c 可以与 a 同时执行,但 async/await 语法会让我们倾向于在 b 执行完后,再执行 c。
所以当我们意识到这一点,可以优化一下性能:
const resA = a();
const resC = c();
await resA;
b();
await resC;
d();但其实这个逻辑也无法达到回调的效果,虽然 a 与 c 同时执行了,但 d 原本只要等待 c 执行完,现在如果 a 执行时间比 c 长,就变成了:
a(() => {
d();
});看来只有完全隔离成两个函数:
(async () => {
await a();
b();
})();
(async () => {
await c();
d();
})();或者利用 Promise.all:
async function ab() {
await a();
b();
}
async function cd() {
await c();
d();
}
Promise.all([ab(), cd()]);这就是我想表达的可怕之处。回调方式这么简单的过程式代码,换成 async/await 居然写完还要反思一下,再反推着去优化性能,这简直比回调地狱还要可怕。
而且大部分场景代码是非常复杂的,同步与 await 混杂在一起,想捋清楚其中的脉络,并正确优化性能往往是很困难的。但是我们为什么要自己挖坑再填坑呢?很多时候还会导致忘了填。
窃认为,不要一昧追求 async/await 语法,在必要情况下适当使用回调,是可以增加代码可读性的。
总结
async/await 回调地狱提醒着我们,不要过渡依赖新特性,否则可能带来的代码执行效率的下降,进而影响到用户体验。同时,笔者认为,也不要过渡利用新特性修复新特性带来的问题,这样反而导致代码可读性下降。
决定代码质量的是思维,而非框架或语法,async/await 虽好,但也要适度哦。
边栏推荐
- 基于 Azuki 系列:NFT估值分析框架“DRIC”
- 强意识 压责任 安全培训筑牢生产屏障
- SWIG教程《四》-go语言的封装
- Analysys and the Alliance of Small and Medium Banks jointly released the Hainan Digital Economy Index, so stay tuned!
- SWIG tutorial "four" - package of go language
- Azure IoT Partner Technology Empowerment Workshop: IoT Dev Hack
- 640. Solving Equations: Simple Simulation Problems
- SWIG Tutorial "One"
- 老板加薪!看我做的WPF Loading!!!
- 舵机内部结及工作原理浅析[通俗易懂]
猜你喜欢

中学数学建模书籍及相关的视频等(2022.08.09)

JS入门到精通完整版

强意识 压责任 安全培训筑牢生产屏障

Lack of comparators, op amps come to the rescue!(Op amp is recorded as a comparator circuit)
![[Gazebo Introductory Tutorial] Lecture 3 Static/Dynamic Programming Modeling of SDF Files](/img/ec/87566763daf7faa3769ee186f93ee0.jpg)
[Gazebo Introductory Tutorial] Lecture 3 Static/Dynamic Programming Modeling of SDF Files

易观分析联合中小银行联盟发布海南数字经济指数,敬请期待!

数学建模学习视频及资料集(2022.08.10)

12海里、24海里、200海里的意义及名称

波士顿房价预测

面试面到了一个腾讯30k出来的,有见识到何为精通MySQL调优
随机推荐
等保2.0一个中心三重防护指的是什么?如何理解?
高薪程序员&面试题精讲系列135之你对分布式是怎么理解的?CAP理论你知道吗?
How to code like a pro in 2022 and avoid If-Else
SWIG教程《二》
1004(树状数组+离线操作+离散化)
Summary of tensorflow installation stepping on the pit
解题-->在线OJ(十九)
Mysql语句分析、存储引擎、索引优化等详情
MySQL Principle and Optimization: Update Optimization
Meaning and names of 12 nautical miles, 24 nautical miles and 200 nautical miles
消息称原美图高管加盟蔚来手机 顶配产品或超7000元
Websocket realizes real-time change of chart content
小程序-语音播报功能
Basic learning of XML
2022年网络安全培训火了,缺口达95%,揭开网络安全岗位神秘面纱
sql语句 异常 Err] 1064 – You have an error in your SQL syntax; check the manual that corresponds to your
Flask框架——MongoEngine使用MongoDB数据库
JS entry to proficient full version
The a-modal in the antd component is set to a fixed height, and the content is scrolled and displayed
BCG库简介