有语言的 async/await 是直接改写成嵌套回调的吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ecnelises
V2EX    编程

有语言的 async/await 是直接改写成嵌套回调的吗?

div id="topic_830605_votes" class="votes">
  •  
  •   ecnelises 2022-01-26 00:26:14 +08:00 2465 次点击
    这是一个创建于 1354 天前的主题,其中的信息可能已经有所发展或是发生改变。

    看到这个隔壁帖子( t/830515 )有感。async/await 的基本逻辑是这样:

    async myFunction() { // some code await readSomething() // 执行至此处函数交出控制权,读取完成后回到此处继续执行 // some code await sendRequest() // 再次交出控制权 } 

    和这个模型最为贴近的是协程(生成器),await 相当于一次 yield ,然后等待外面 call 自己的作为调度器的某个东西再 resume 进来。Swift 5.5 加入了 async/await ,把这个调度器做到了系统的事件循环里,所以(起初)需要新系统支持。

    然后查了一下 TypeScript 和 Rust 的实现,都是基于状态机,原理其实和 Swift 的类似。但换种方向直观理解,async/await 好像也可以改写成嵌套回调,比如:

    // some code readSomething(() => { // some code sendRequest(() => { // some code }) }) 

    因为有闭包,所以循环也可以通过改成尾递归再写成这种格式。了解了下这种格式有个学名叫 Continuous-passing style ( https://en.wikipedia.org/wiki/Continuation-passing_style ),看起来也很合理。但为什么很多编程语言都选择了另一种实现方式呢?

    10 条回复    2022-01-26 09:54:25 +08:00
    lhx2008
        1
    lhx2008  
       2022-01-26 00:30:44 +08:00
    还是 go 的写法比较符合人类直觉
    shenzye
        2
    shenzye  
       2022-01-26 00:53:01 +08:00 via Android   1
    按我的理解,async/await 直接改写成嵌套回调是一种有成本的抽象。嵌套回调通过闭包传递变量,那么整个方法执行下来,需要占用所有被使用过的变量的空间(比如使用过然后又释放掉的变量也会占用空间),而基于状态机的异步实现,可以重复利用已经不再使用的变量的空间。
    如若有误,感谢各位指正
    xarthur
        3
    xarthur  
       2022-01-26 00:56:57 +08:00 via iPhone
    因为回调的写法会有回调地狱( callback hell )。
    而且你可以试试在回调的写法里来处理错误,会更加头痛。
    其实最好的处理方法还是 do notation
    xarthur
        4
    xarthur  
       2022-01-26 01:02:03 +08:00 via iPhone
    另外 CPS 也是可以转换成同步的写法的,你可以搜索「 CPS 变换」。
    molvqingtai
        5
    molvqingtai  
       2022-01-26 01:57:57 +08:00 via Android
    问反,就是因为回调地狱,才使用 async/await
    eason1874
        6
    eason1874  
       2022-01-26 02:07:20 +08:00
    JS 近几年才有 async/await ,以前写异步只能回调,别提多难受了,一个事务里有多个异步调用的时候只能把上下文传入回调函数,传来传去
    Rocketer
        7
    Rocketer  
       2022-01-26 02:17:09 +08:00 via iPhone
    我学 ES6 的时候,教程里说 await 就是语法糖,它最终会被编译成回调。
    autoxbc
        8
    autoxbc  
       2022-01-26 02:39:38 +08:00
    JS 不是一下子只引入 async/await 的,而是和 Promise ,Generator 一起引入的,所以把 async/await 渐进的 polyfill 成 Generator ,Promise 是比较自然的。就像要去 4 楼,可以从 1 楼坐电梯,不过如果刚好也要去 2 楼 3 楼,那不如一层一层爬楼梯
    EPr2hh6LADQWqRVH
        9
    EPr2hh6LADQWqRVH  
       2022-01-26 08:29:39 +08:00 via Android
    这个你自己都说了 async await 里面有一个调度器在里面,需要的就是一个中断执行的能力,你看嵌套能中断执行吗,而且执行中断之后 cpu 要交给别的任务的,这样的任务还很多
    系统里有一万任务在跑,需要来回调度,嵌套的话这调用栈怎么办

    而且我不太明白你站在哪里在思考这个问题,你是站在运行时编译器的角度在思考还是在应用程序的角度思考
    4ark
        10
    4ark  
       2022-01-26 09:54:25 +08:00 via iPhone
    可以了解一下代数效应和纤程
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2639 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 13:53 PVG 21:53 LAX 06:53 JFK 09:53
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86