ATscore

  • 首页
  • 听音乐
  • 科普
  • 冒险岛
  • 声明
  • 关于
  1. 首页
  2. 信息技术
  3. 正文

对JS中async/await的简单理解

2023年8月20日 273点热度 0人点赞 0条评论

file

对async/await的简单理解

之前改nodejs代码,遇到async/await,没有好好搞懂。今天温习一下,查了些资料,网上的资料,尤其是某傻乎真是写的奇复杂无比,简单问题搞的这么复杂。

写点心得,以享来者。

async的动机

JS程序可能会有多个线程,在一个线程上,进入一个函数,走出一个函数。所谓线程串行执行。
但是一些函数,它会因为系统调用(system call)进入等待。这样执行效率就不算太高。
JS使用async标注一个函数,这个函数在执行时,是异步的。即,即使这个函数没执行完,在等待的时候,JS也可以继续执行后面的代码。
你以为是async造成的异步执行?其实并不是。

await的设计

JS是在遇到await时才异步执行的。即遇到await函数JS就执行非阻塞操作然后立即就返回,同时(我估计)另开一线程用于执行await及后面的语句。

JS一些古怪的坚持和设计,需要用奇怪的方式来声明非阻塞和等待

说一个优秀设计的例子。
MPI语言,它让handle关联非阻塞操作,并使用显式的wait来等待具体的异步操作。围绕句柄就可以制造出如回调等方式。虽然语言工作在low level上,但这非常直观。

我不喜欢JS的设计。它在async函数内使用await,看似聪明,但却把函数分为了“普通函数”和“异步函数”。事实上,并没有异步函数,只有异步操作,包含异步操作的函数就变成了异步函数,这看上去多少有点牵强。

//使用timeout来模拟长时系统调用,返回字符串
async function test() {  //这里用async或者不戴,都可以
    setTimeout(()=>{}, 1000);
    return "hello world";
}

//异步调用,获取字符串,并打印
async function say() {
    v = await test();
    console.log(v)
}

//执行异步调用,主线会跳过say()中的log,先执行log("end"),然后待say()中的await结束后,打印了hello
say();
console.log("end")

输出:
end
hello

走一遍例子的控制流

主线:进入say(), 不管say()的async标记,继续走。遇到await test(),非阻塞启动test(),然后立即从say()返回。执行第二句log("end"),于是stdout上显示end。主线结束了。

次线:进入test(),先睡1s,然后返回promise("hello")。(为什么会有promise,原理请自行查询),从test()返回后,await解包promise,将"hello"传给v,并打印。于是在stdout上,我们看到end之后又输出了一句hello。次线结束。

总结

这就是async与await的用法了。函数肚子里有需要长时等待的子函数,就给函数戴上async的帽子,并在子函数处用await等待。主线在执行时就会非阻塞地执行函数,并实际在子函数处等待。

奥妙

奥妙在于await什么函数。
await一个async函数是可以的,await一个普通函数也是可以的。
js让async函数返回值打包成一个promise,而await对promise做解包
如果await的不是一个async函数,那它对返回值不做什么。

评价

我觉得这种设计不太好。真的不好。拗口,牵强。
你真不如像mpi那样关联一个等待句柄,然后围绕句柄构建回调或者等待。

ATscore

用常识解读世界,用自己的大脑独立思考

Post Views: 275
标签: 暂无
最后更新:2023年8月20日

ATscore

用常识解读世界,用自己的大脑独立思考

点赞
< 上一篇
下一篇 >

文章评论

取消回复

ATscore

用常识解读世界,用自己的大脑独立思考

文章目录Toggle Table of ContentToggle
  • 对async/await的简单理解
    • async的动机
    • await的设计
      • JS一些古怪的坚持和设计,需要用奇怪的方式来声明非阻塞和等待
    • 走一遍例子的控制流
    • 总结
    • 奥妙
    • 评价

COPYRIGHT © 2022 atscore.cc. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS