有没有把 Promise, Generator, 和 async/await 之间的关系讲解得比较清楚条理的文章或者博客? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yazoox
V2EX    问与答

有没有把 Promise, Generator, 和 async/await 之间的关系讲解得比较清楚条理的文章或者博客?

  •  
  •   yazoox 2020-05-09 18:35:07 +08:00 3804 次点击
    这是一个创建于 1982 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如果,正在学习前端开发。对这几块有点迷糊。

    感觉好像是 先有 Promise, 再有 generator,然后现在又有了 async/await

    好像越来越“先进”和“简单”。

    有没有对这三者的理解 /解析比较好的文章或者博客,想理解得更深入一些?

    谢谢!

    28 条回复    2020-05-11 09:15:25 +08:00
    woodensail
        1
    woodensail  
       2020-05-09 18:40:58 +08:00
    先有 promise,解决了回调地狱的问题。但是副作用是一段逻辑被切分到多个作用域中,且 return 和异常都被拦截。因为本质上 js 一个函数必须同步执行完毕,想实现异步只能用多个函数来实现。

    然后有了 generator,generator 的创举在于允许一个函数执行到一半挂起,等异步回调后继续执行,完美的解决了 promise 带来的副作用。

    而 async/await 本质上是 generator 在特殊场景下使用时的一个语法糖而已,省得你去依赖 co 模块了。

    至于文章手头还真没有,毕竟也是很老的东西了……
    ClericPy
        2
    ClericPy  
       2020-05-09 18:44:57 +08:00
    平时遇到问题都直接看 MDN 的, 非要找教程的话,

    现代 Javascript 教程 - https://zh.Javascript.info/

    是我之前看的, 感觉有点其他语言基础, 理解起来应该不费劲, 至于更深入... 得看想多深了
    woodensail
        3
    woodensail  
       2020-05-09 18:47:04 +08:00
    另外再说下关于语法糖的问题,我一般把 async/await 看做 generator,因为 async/await 核心的异步挂起和作用域保持功能已经在 generator 实现了,就算没有 async/await,要不了多少代码也能封装类似的功能出来。

    而 promise 到 generator 虽然也能通过 regenerator 的方式来实现,但是缺少作用域保持和异步挂起。
    只能通过套一个函数保持作用域,然后多次调用同一个方法,通过 switch case 方式来分片执行。而你的原始代码也被编译得面目全非。是个非常不优雅的 hack 手段。远不如原生的 generator 好。
    noobsheldon
        4
    noobsheldon  
       2020-05-09 19:01:54 +08:00
    Angular Observable
    kidlj
        5
    kidlj  
       2020-05-09 19:04:51 +08:00 via iPhone
    阮一峰有一系列几篇博客,从回调,函数科里化,讲到 promise,过渡期的 co 库的实现,然后到 async/await. 非常不错。
    sunjourney
        6
    sunjourney  
       2020-05-09 19:13:18 +08:00
    @woodensail #3 又是一个阮一峰文章的受害者
    helloSpringBoot
        7
    helloSpringBoot  
       2020-05-09 19:39:09 +08:00
    lizheming
        8
    lizheming  
       2020-05-09 21:09:08 +08:00 via iPhone
    CosimoZi
        9
    CosimoZi  
       2020-05-09 21:09:49 +08:00
    continuation 的不同表现形式而已.万变不离其宗.
    giuem
        10
    giuem  
       2020-05-09 21:17:42 +08:00 via iPhone
    https://zhuanlan.zhihu.com/p/83965949 看这篇文章的后半段
    JayLin1011
        11
    JayLin1011  
       2020-05-09 22:56:25 +08:00
    可以看一下阮一峰老的教程,深入出步程=。=
    zhuowenli
        12
    zhuowenli  
       2020-05-09 22:59:43 +08:00 via Android
    《你不知道的 Javascript 》中卷
    mxT52CRuqR6o5
        13
    mxT52CRuqR6o5  
       2020-05-10 02:56:30 +08:00 via Android
    Promide 搞明白,async/await 自然就明白了,async/await 是 promise 的语法糖
    autoxbc
        14
    autoxbc  
       2020-05-10 05:02:02 +08:00
    尽管 Babel 的 async/await 是基于生成器实现的,然而在逻辑关系上,完全可以略过生成器,从 Promise 直接到 async/await

    学习路径是
    1. 彻底了解 Promise 的工作逻辑,注意工作逻辑不是实现细节
    http://liubin.org/promises-book/

    2. async/await 完全当成 Promise 的语法糖
    async 就是在包装 Promise,await 就是解开 Promise
    ysc3839
        15
    ysc3839  
       2020-05-10 07:17:37 +08:00 via Android
    @woodensail Promise 没解决回调地狱,传递给 Promise then 的还是一个个回调函数。async function 才解决了。
    按照我的理解,Promise 是提供了一个通用的异步回调和返回值的工具库。没有 Promise 的时候,异步回调一般是把回调函数作为函数参数传递进去,不同库的接口各不相同。有了 Promise 之后,大家都可以用一个统一的接口,可以简化开发。
    ciaoly
        16
    ciaoly  
       2020-05-10 07:43:26 +08:00 via Android
    @sunjourney 何以出此言?阮一峰的博客写的不对吗?
    chengzi168
        17
    chengzi168  
       2020-05-10 08:32:22 +08:00 via Android
    @sunjourney 求解释,阮一峰的文章不对么?
    woodensail
        18
    woodensail  
       2020-05-10 14:48:46 +08:00   1
    @ysc3839 额,那是你用法不对,promise 的正确用法是 fun1().then(fun2).then(fun3)这样,无论多少个异步操作,只需要一层回调即可。缺点就是上面说的你没法直接 return,想 rutern 就只能抛异常,然后就把异常信息污染了。
    ysc3839
        19
    ysc3839  
       2020-05-10 15:07:21 +08:00 via Android
    @woodensail 我知道是这样一个个 then,但是还是把整个代码逻辑拆分成了一个个回调函数。
    woodensail
        20
    woodensail  
       2020-05-10 15:11:33 +08:00
    @sunjourney 那啥,不知道你为什么会这么认为,但是我确实没读过他的文章
    ysc3839
        21
    ysc3839  
       2020-05-10 15:12:42 +08:00 via Android
    @woodensail 而且不对呀,这是针对一个 Promise 的情况,假如第一个 Promise 执行成功了,要执行另一个 Promise,还是会变成那种回调嵌套的情况。
    woodensail
        22
    woodensail  
       2020-05-10 15:13:22 +08:00   1
    @ysc3839 是的啊,我上面也说了,promise 在解决回调地狱后也带来了作用域分裂,流程控制困难等新的问题,不是个完美的解决方案。直到 generator 诞生才彻底解决了问题。
    woodensail
        23
    woodensail  
       2020-05-10 15:14:48 +08:00   1
    @ysc3839 你看我写的,then 是可以链式调用的,fun1().then(fun2).then(fun3).then(fun4).then(fun5)
    只额外包了一层而已。
    不会出现回调地狱那样左边 tab 半个屏幕的情况。
    woodensail
        24
    woodensail  
       2020-05-10 15:23:55 +08:00   1
    @ysc3839 @ysc3839 接上面那个例子说下 promise 解决回调地狱后带来的新问题。

    1:作用域分裂,比如 fun3 中请求的得到的结果在 fun4 要使用,但是直接在 fun3 和 4 的作用域不是同一个。所以直接在 fun3 中定义变量无效,必须把变量声明提前到 fun1 执行之前。

    2:流程控制困难,比如 fun2 中请求结果显示流程不能继续执行,需要退出。
    这时候没法跳过 345 的执行,要么 fun2 通过变量或返回值来通知,在 345 的开头分别判断一下标志,有标志就直接退出。
    或者直接抛异常来跳过后面的步骤,但这样一样,业务流程就和真正的异常混在了一起,给异常治理带来了麻烦。
    ysc3839
        25
    ysc3839  
       2020-05-10 15:25:33 +08:00 via Android
    @woodensail 查了下文档,是我孤陋寡闻了。then 的回调函数可以返回一个 Promise,下一个 then 的回调就会在返回的那个 Promise 完成时被调用了。
    woodensail
        26
    woodensail  
       2020-05-10 15:37:40 +08:00
    @ysc3839 嗯,我当年刚知道 promise 这个特性的时候非常兴奋,然后很快就被业务教做人了。
    一个医保的业务,需要
    1:访问自家服务器获取订单信息(包含多个账单)
    2:访问医保服务器做预结算
    4:循环访问医保服务器,一个一个创建账单
    3:访问自家服务器记录账单
    5:循环访问医保服务器,一个一个确认账单
    5:访问自家服务记录结果
    其中任何一步失败都要跳过后续步骤,并且记录失败信息。如果失败时已经有部分账单被创建需要进行取消;如果有部分账单已经确认,需要进行退费。

    最后用皮肉面色写出来一坨屎山,太绝望了,过去这么多年,我都再也没碰到过这大的屎山了
    yazoox
        27
    yazoox  
    OP
       2020-05-11 08:41:58 +08:00
    @woodensail 兄弟,既然你觉得 Promise 不能很好处理这个“医保”问题。
    时隔多年,现在有了 async/await 了,能否很漂亮的解决当年的这个问题呢?

    我觉得这个问题很值得花点时间研究一下。

    如果你有空的话,可能分享给我们大家。(别忘记了 @我一下)
    woodensail
        28
    woodensail  
       2020-05-11 09:15:25 +08:00
    @yazoox 后来有想过,不过已经跳槽了也就不管了。如果用 async 的话有几个优势,首先整个流程在同一个方法中,可以随时 return 退出后续步骤,在扫尾处理方面会简单很多。
    另外由于 async 中可以直接 for 循环执行异步语句,所以不需要用 promise 迭代的方式来顺序执行数组中的任务,也让代码可读性大幅提高。

    整体的话估计开发难度不到原来的一半,代码量下降不多但是可读性大幅提升。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2820 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 13:32 PVG 21:32 LAX 06:32 JFK 09:32
    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