我一直很奇怪的一个问题是,async/await 比 yield 好在哪里?除了前者是标准,而后者比较 hack 之外。
在我眼中,前者作为标准,应该是会来到的。而后者作为一种 hack 的方式,虽然不是 generator 的本意,但它的实现既不会发生大的更改,也不会 deprecated。那么 yield 的用法就可以一直用下去,不用担心后续兼容的问题。
就功能来说,我觉得 await 只是 yield 的子集。yield 可以接收数组来并发,也可以接收 object 来并发。而 await 貌似只能一次执行一个 promise 吧?
就使用习惯的发展来看,大家在用 await 的过程中,由于 await 是一个语言上的实现,所以只能按js设计者的意思工作,而去看看 co 的实现,会发现 yield 只是起了中介的作用,你可以让 yield 接受各种参数,只要说得过去。这也是为什么 yield 能把 promise 和 chunk 一视同仁的原因。
这么说起来,我感觉 yield 是比 await 优越的。
这个问题目前也困扰着我,目前我自己只实践到Promise为止 感觉规范维护者倾向于认为async/await是最终的异步解决方案,所以大家在思想上更容易靠近政治正确? 中央已经讨论决定了就是你了,是不是有种钦定的感觉?
来自酷炫的 CNodeMD
@i5ting 人真高手都上升到语言的高度来理解的,你呀,非得把那层皮给扒拉下来,你让人家装会逼成么?
语义,语义,语义,重要的事情说三遍,懂了么?
一年一个标准,我是非常,非常,非常看好这样的语言的,重要的事情说三遍,三个非常,就如我看好C++一样,这种标准委员会规范出来的语言那都是集各编程语言之精华的,那都是真真切切要解决程序员的疾苦的。
我觉得大家都在说什么亲生的小三的,什么生成器本来不是这样设计用的,有那么复杂吗?难道现实世界中,你不能拿扳手来敲钉子么? 我家里的窗户装修的时候没弄好,防盗网和墙壁之间有很大的缝隙,夏天蚊子就进来了,我就是拿防撞胶裁剪合适了,塞到缝隙里的,为了压实,最后最趁手的工具居然是衣架!请问完成这些工作,有那样是所谓专业的工具? 还有刚刚看的帖子,elem这个新语言,作者鼓吹他的语言多纯,知乎就有吐槽。所以可见,世界并不是人类想象的那样运行的,即使是人类自己创造的工具。
分享一个链接 http://rossboucher.com/await.
- 为了干掉回调地狱,出了个 promise
- 但 promise 也不是万金油,
then().then().then().
,这种代码写多了,代码量也没减多少,也想吐 - 为了解决 promise 的坑,为了语义,开发体验,最佳实践吧,出了 async/await,代码量确实减少了很多
- Node 还是单线程
虽然都处理异步编程的问题,但这些东西并不是完全相互替代的关系 calback => promise => yield (async/await)还有RxJS,因为一段程序不止处理返回值与传参接口,还需要处理side effect,这就像类设计要getter,setter,而不直接用属性赋值。所以会有不少情况一个callback和一个promise比async/await实用的情况,或者说在一些程序里,async/await并不是关键的程序结构,而是一种语法糖而已,真正的核心仍然是一个Promise序列。
@huangyanxiong01 可能你跟 @fundon 对于多线程的理解不一样。我指的是看这个 await 问题的角度不一样。
child_process 那已经是新开一个进程了。在当前进程中,js无论如何都是单线程的,libuv那层面的多线程 file io 不能算进来。
@alsotang async/await 相对于 Generator,1)语义上更容易理解一些 2)async/await 更规范一些,后面只能接 Promise,并且返回的也是 Promise,而 Promise 对开发者也是隐形的。而 Generator 只是迭代器的一个子类型,设计时并不是拿来解决异步问题,只是我们发现可以用来解决问题。Generator 执行时需要借助第三方执行器,如:co,最后支持哪些功能需要依赖第三方执行器包装了哪些东西。co 里使用 Promise(用其他也是可以的),抹平了 yield 和 yield * 的差异,yield 后面是数组的话自动加 Promise.all 来并行执行。
只要任何东西都可以变成一个Promise之后,await的功能不会比yield弱的。 https://github.com/JacksonTian/tinywork (注意名字) 要理解async/await还得先理解Promise的意图,Promise带有延迟求值的意思(更多细节参见:http://alinode.aliyun.com/blog/5 ),async/await就是为之在语义上的准备。 Generator目前在co的帮助下能实现async/await的功能,但async/await是不需要借助外部工具即可用的。
我个人还是比较喜欢yield 因为 object 和 array 并发很方便,而async实现并发后在手动把并发后的内容整合到object中,反而代码要冗余很多。。async的优点是原生语法,语意更好,但我觉得效率上yield这样的hack也并不会逊色很多。。。 可能重要的缺点是async这种对于新人来说比较容易理解,而yield被co包装后不太容易理解吧 所以,我觉得对于老司机来说,yield array 和 yield {} 要比 async promise… 来的更方便吧。。。
可能我又要挨骂了。。。。
@welefen 而 Generator 只是迭代器的一个子类型,设计时并不是拿来解决异步问题 真是一言惊醒梦中人,按照这么说generator的设计初衷应该就是用来做循环迭代之类的工作,因为它本质上市一个迭代器?
拿 async/await 做對比就真的有點 naive 了,當你們嘗試在前端中使用 async/await 后,就會知道由 TJ 創造的 Generator 另類用法的侷限性是多麼嚴重。至於 Generator 的真正意義?直接傳送門吧 https://zhuanlan.zhihu.com/p/20794401。
可参考Kyle Simpson的博文。 generators 强在代码流程控制;async functions 侧重函数值传递。
async/await is nothing more or less than the way to consume and return promises. As that’s what a huge amount of JS code does, hence it exists.
If you’re consuming and returning promises, use async/await and move on.
If you’re doing something else besides consuming/returning promises, then sure, async/await is not for you, and this includes building your own for coroutine system with whatever unique quirks you want to bake in.