当前位置:网站首页>关于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 虽好,但也要适度哦。
边栏推荐
- FPN详解
- 易观分析联合中小银行联盟发布海南数字经济指数,敬请期待!
- In the second half of 2012 system architecture designers afternoon paper II
- Websocket realizes real-time change of chart content
- systemui屏蔽通知栏
- E. Cross Swapping (and check out deformation/good questions)
- PAT甲级 1014 排队等候(队列大模拟+格式化时间)
- Appium进行APP自动化测试
- numpy.meshgrid()理解
- 无线网络、HTTP缓存、IPv6
猜你喜欢
SWIG Tutorial "One"
Rich Dad Poor Dad Reading Notes
从洞察到决策,一文解读标签画像体系建设方法论
Redis -- Nosql
Do not access Object.prototype method ‘hasOwnProperty‘ from target object....
易基因|深度综述:m6A RNA甲基化在大脑发育和疾病中的表观转录调控作用
字节终面:CPU 是如何读写内存的?
关于已拦截跨源请求CORS 头缺少 ‘Access-Control-Allow-Origin‘问题解决
It is reported that the original Meitu executive joined Weilai mobile phone, the top product may exceed 7,000 yuan
池化技术有多牛?来,告诉你阿里的Druid为啥如此牛逼!
随机推荐
Classifying irises using decision trees
[Gazebo Introductory Tutorial] Lecture 3 Static/Dynamic Programming Modeling of SDF Files
Pagoda panel open Redis to specify the network machine
How does vue clear the tab switching cache problem?
Introduction to the Internet (2)
usb转rs485测试软件,usb转rs485「建议收藏」
高薪程序员&面试题精讲系列135之你对分布式是怎么理解的?CAP理论你知道吗?
池化技术有多牛?来,告诉你阿里的Druid为啥如此牛逼!
使用mysq语句操作数据库
Second half of 2011 System Architect Afternoon Paper II
2022年网络安全培训火了,缺口达95%,揭开网络安全岗位神秘面纱
正则表达式(包含各种括号,echo,正则三剑客以及各种正则工具)
兆骑科创高层次人才创业大赛平台,投融资对接,双创服务
MQTT服务器搭建
Mini Program-Voice broadcast function
E. Cross Swapping (and check out deformation/good questions)
蓝帽杯半决赛火炬木wp
【语义分割】DeepLab系列
《论文阅读》PLATO: Pre-trained Dialogue Generation Model with Discrete Latent Variable
High-paid programmers & interview questions series 135 How do you understand distributed?Do you know CAP theory?