V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
love
V2EX  ›  JavaScript

js 为什么一下子要上马二个语言级异步转同步方案

  •  
  •   love · 2015-07-28 11:30:19 +08:00 · 4595 次点击
    这是一个创建于 3410 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一个promise+async语句,一个generator,本来要摆脱callback hell是好的,但一下子来俩就有点重复了吧,都不知道要用哪个好了,选择太多也是累。


    py3就只有一种,现在v3.4的用generator,v3.5加一个async语法糖,做一件事只用一个方法。
    28 条回复    2015-07-29 11:18:47 +08:00
    picasso250
        1
    picasso250  
       2015-07-28 13:28:27 +08:00
    > 一个promise+async语句,一个generator

    they are different
    ShiningRay
        2
    ShiningRay  
       2015-07-28 13:38:09 +08:00
    generator 本身不是为了把异步转同步诞生的,如果是的话,应该会直接叫 Fiber/Coroutine 而不是 generator
    generator 本身是一个 semi corountine,当然使用一些模式,也是可以达到类似效果的。
    sox
        3
    sox  
       2015-07-28 13:41:45 +08:00 via Android
    如果你能搜索 /t/135335
    love
        4
    love  
    OP
       2015-07-28 13:44:41 +08:00
    @picasso250 我就是说这二个是不同的啊,但可以达到一样的以同步方式写异步逻辑的效果。

    @ShiningRay 但generator同时也是最好的转同步方案啊,发明一样东西又不是一定要限制在最原始的用法上,你看python的语言级转同步支持就是基于generator的。
    sodatea
        5
    sodatea  
       2015-07-28 13:50:03 +08:00 via iPad
    1. generator 并不是为了处理异步而引入的,只是恰好可以用来这么做而已;
    2. async/await 是 ES7,promise 和 generator 是 ES6,并不同时;
    3. async/await 只是语法糖,它能做到的事用 promise + generator 也一样行,它只是把 spawn 函数包装了下看起来好看点而已。
    love
        6
    love  
    OP
       2015-07-28 14:01:06 +08:00
    @sodatea ES6不是刚刚才标准化的嘛,标准化之前generator提案也早有了,在没放进标准前从别的语言抄了个更好的方案来后不是应该一脚踢开原先的吗,一但放进标准以后再也没机会去掉了。 当然你要说Promise在JS上古时代就有了,一直在发展,现在好不容易可以转正了就别把之前的努力白费了(来都来了)。

    我的意思是说同样功能的选择越少越好,只选一个最佳的,特别是在语言级的标准上,Python 3.5也有async语法糖,但它是基于generator的,也就是说python只用一套方案就能达到js二套的效果。
    sodatea
        7
    sodatea  
       2015-07-28 14:11:27 +08:00 via iPad
    @love 没懂你说的……generator 是基础设施,不仅限于异步处理,肯定不能丢,async/await 得基于 Promise,后者自然也不能少(对了,你说的 generator 处理异步,也是得和 Promise 一起用的)。标准化需要时间,所以一步一步来,先打好基础,语法糖后续再加。

    JS 里的 async/await 本质上就是基于 generator + Promise 的,跟你说的 Python 一套方案达成两个效果有区别吗……

    以及这里有篇 Does async/await solve a real problem? 可以看一下 https://esdiscuss.org/topic/does-async-await-solve-a-real-problem
    picasso250
        8
    picasso250  
       2015-07-28 16:08:22 +08:00
    @love 我说的是generator能做的事情不知道多到哪里去了。怎么能去?
    但你要是用generator直接async吧,难度有点高,写成库吧,也可以。所以你的问题应该是:为什么async不用generator实现?
    otakustay
        9
    otakustay  
       2015-07-28 16:47:13 +08:00
    1. promise是异步统一接口
    2. generator中的async generator“正好”可以搞异步
    3. async接口层面用promise,实现层面用generator

    generator是很好的异步转同步方案,但并不是“最好”的,就说几个最基本的缺点

    1. promise可以通过继承等手段加上额外的逻辑,比如xhr.abort(),generator要这么做得用observer,整个接口都不直观了
    2. generator对外表现的形式是“未知有多少东西”,promise则明确“有一个结果”,用generator去表达异步会让人很尴尬,到底要不要判断done呢,后面会不会有别的东西呢,没有足够的表意性
    ariestiger
        10
    ariestiger  
       2015-07-28 17:01:10 +08:00   ❤️ 1
    应该是两个而不是二个吧
    morethansean
        11
    morethansean  
       2015-07-28 17:07:30 +08:00
    真正异步等 async 吧。generator 的实现调试起来简直就是地狱。
    love
        12
    love  
    OP
       2015-07-28 18:10:35 +08:00
    @otakustay 用generator来表示统一接口也没有什么不好,至少没必要到用二套基本底层异步接口。

    你所有缺点:
    1. 没理解你的例子。
    2. generator无数据了/运行完成了表示done有什么不好判断呢?
    FrankFang128
        13
    FrankFang128  
       2015-07-28 18:13:36 +08:00
    所以说前端不是那么简单的。
    而且 await 、promise 这么简单地模式很难理解么
    jeansfish
        14
    jeansfish  
       2015-07-28 18:20:00 +08:00   ❤️ 1
    @ariestiger 终于看到这个槽点了
    love
        15
    love  
    OP
       2015-07-28 18:27:09 +08:00
    @sodatea async没不是一定要Promise,接在generator也可以,而且实现更简单,几乎就是个语法糖。
    @morethansean 具体什么情况?我用python的基于generaotr的asyncio写了几千行代码没有发现有调试问题。
    @FrankFang128 你是不是看错题了?
    morethansean
        16
    morethansean  
       2015-07-28 18:58:43 +08:00
    @love ……你真的看了那几个用 generator 的库实现异步的原理么…… 然后你写点复杂的程序,开始调试的时候就明白痛苦在哪了。
    FrankFang128
        17
    FrankFang128  
       2015-07-28 19:00:20 +08:00
    @love 题外话
    love
        18
    love  
    OP
       2015-07-28 19:08:44 +08:00
    结贴吧我知道为什么了。


    @FrankFang128 我说了promise很难?另外promise虽简单但你不用async直接手写promise代码同样是陀屎,一样会把逻辑分隔得很不直观。
    otakustay
        19
    otakustay  
       2015-07-28 20:00:04 +08:00
    @love 在我看来“表意性”和“能用”同样重要,promise明确表达是“做一件事,只有成功和失败2种结果”,而generator没法表达这个概念,或者说generator承载的概念太多导致使用者拿到一个generator function的时候无法确定它是不是正在表达着“做一件事”这个概念
    你的思路在前端看来类似于“只要div就能做网页了还要其它元素干啥”……
    FrankFang128
        20
    FrankFang128  
       2015-07-28 20:33:51 +08:00 via Android
    @love 没说你说过,我只说想表达JS很复杂了已经。新加的语法只会徒增概念。
    love
        21
    love  
    OP
       2015-07-28 20:37:40 +08:00
    @otakustay 我倒是觉得从表意性上generator也说得过去。yield可以看作异步return,和有同步return的函数互补,比生造一个Promise概念上更简单,只是和同步return不同的是表面上返回的是个数据list而不是return的单个数据,但这个差别很小,一点点不完美而已,python这么追求完美的语言还不是用generator来作为异步底层。
    jiongxiaobu
        22
    jiongxiaobu  
       2015-07-28 20:58:54 +08:00
    两个不是马上出来的 generator是es6里的,很早就有。async是es7里的,最近才有
    sodatea
        23
    sodatea  
       2015-07-28 22:27:45 +08:00 via iPad
    @love 明白了,你是在说有了 generator 后不需要 promise?
    这里有段话可以解释 https://www.promisejs.org/generators/
    What generators do not do is give us a way of representing the result of an asynchronous operation. For that, we need a promise.
    sodatea
        24
    sodatea  
       2015-07-28 22:33:30 +08:00 via iPad
    @love 我觉得 generator 的语义更倾向于 lazy sequence 吧……用在异步稍微牵强了点,不过这不是重点。
    另外 Promise/Future 的概念并不是生造的,很多其他语言也有啊 https://en.m.wikipedia.org/wiki/Futures_and_promises

    除了这些,我个人还觉得 Promise 比较有用的一点是它可以很容易地被 polyfill……这在前端很重要。
    love
        25
    love  
    OP
       2015-07-28 23:08:37 +08:00
    @sodatea 对啊我就是这个意思,yield本身是个很通用的概念,同时包含lazy/异步/数据流语义,用它来作同步化方案也是可行的且不用让大家再学promise了,你看人家python这么做没什么不好的地方,也让大家少点学习负担。当然现在看来js语言本身根本没有想要用generator来做同步化方案而是完全用promise,本来手写promise体验很渣,但加上async语句后和generator方案有一拼了,所以用promise方案也不能说不好。
    ysmood
        26
    ysmood  
       2015-07-28 23:36:27 +08:00
    @love 你为啥要说“二个语言级异步转同步方案”呢?这个说法就不对啊,为什么 yield 就被对号入座了呢?这个官方有推荐这种用法吗?ES 的作者们都没这么说。只是有些人比如 TJ, hack 了一下 yield 的一种特性而已,而且被很多一知半解的人宣传的变了味道。

    换个说法,我能用 swich case 完成全部的 yield 的功能,那是不是说 switch case 能算第三种 异步语法了呢?很多方法都是能简化异步问题的,哪止一两种,即使是 callback,不谈 js,即使在 C 编程刚流行这个概念的时候也是解决很多棘手的异步问题的,只不过随着时间的推移需求变得更复杂了,人们又开始寻找能解决当下问题的工具而已。

    我敢说用不了几年当 async await 被大量使用后,人们能解决更多更复杂问题的时候又会有新的语法被发明出来。不说未来,即使是现在就有很多玩转了 yield async await promise 开始抱怨它们的总总问题了。有兴趣的话,可以去 MDN 订阅个 mailing list 看看业内人士们是如何讨论未来的,最近两天就有几个哥们一直在讨论 async 的各种问题。
    magicyu1986
        27
    magicyu1986  
       2015-07-29 03:01:31 +08:00
    你知道JS这类语言的实质都是——啰嗦。还记得null 跟 undefined 不?

    老老实实给个 coroutine 实现不好么,为毛要搞出三个幺蛾子呢。
    denghongcai
        28
    denghongcai  
       2015-07-29 11:18:47 +08:00
    Generator可以直接使用try catch,哪来的调试坑

    爱用Promise就Promise,爱用Generator就Generator,这有什么争得
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2968 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 00:31 · PVG 08:31 · LAX 16:31 · JFK 19:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.