说说还在 stage3 的 async/await, 还在裸奔着 generator or 裸奔着 promise 的进 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
magicdawn
V2EX    Node.js

说说还在 stage3 的 async/await, 还在裸奔着 generator or 裸奔着 promise 的进

  •  
  •   magicdawn 2016-04-10 11:52:00 +08:00 5370 次点击
    这是一个创建于 3547 天前的主题,其中的信息可能已经有所发展或是发生改变。

    CNode https://cnodejs.org/topic/5709cb2f94b38dcb3c09a7ac


    async/await

    提议 https://tc39.github.io/ecmascript-asyncawait/ 目前在 stage3, 没赶在 ES2016 即 ES7 的 deadline 之前达到 stage4, 所以只能赶下波 ES2017 了。 已经用上 babel 的可以不用往下看了~不是你们的菜~

    async function foo(){ let b = await bar(); return b + 1; } 
    • 调用 bar() 的返回值是一个 Promise 实例
    • foo 函数中可以去等待 bar 的执行,类似线程 join
    • 调用 foo() 的返回值是一个 Promise 实例,可以被其他 async function await

    但是只要满足一点就可以了,返回值是 Promise 类型,即可称之为 aysnc function. 例如

    function bar(){ return Promise.resolve(1); } // or async function bar(){ return 1; } 

    这两种形式对于使用者 foo() 来说没有任何不同。

    desugaring

    see https://tc39.github.io/ecmascript-asyncawait/#desugaring 在 async/await 语法糖之下是什么呢

    async function <name>?<argumentlist><body> => function <name>?<argumentlist>{ return spawn(function*() <body>, this); } 

    是有一个 spawn 函数来帮你运行一个 generator, 并返回一个 spawn 的返回值。 proposal 里给出了 spawn 的实现

    function spawn(genF, self) { return new Promise(function(resolve, reject) { var gen = genF.call(self); function step(nextF) { var next; try { next = nextF(); } catch(e) { // finished with failure, reject the promise reject(e); return; } if(next.done) { // finished with success, resolve the promise resolve(next.value); return; } // not finished, chain off the yielded promise and `step` again Promise.resolve(next.value).then(function(v) { step(function() { return gen.next(v); }); }, function(e) { step(function() { return gen.throw(e); }); }); } step(function() { return gen.next(undefined); }); }); } 

    可以去看 co 的源码,跟 co 差不多, co 要多一些将其他非 promise 值转为 promise 的过程。 所以可以这样使用

    function foo(){ return co(function*(){ let b = yield bar(); return b + 1; }); } 

    这个 foo 跟 前面的 async function foo() { ... } 对于使用者来说没有任何区别, (foo.length 除外, 待会说). 于是可以使用一个方法去生成这样一个用 generator 写的 aysnc function

    // 使用 co.wrap let foo = co.wrap(function*(){ let b = yield bar(); return b + 1; }); // 使用 bluebird.coroutine let foo = bluebird.coroutine(function*(){ let b = yield bar(); return b + 1; }); 

    所以推荐使用 co.wrap & bluebird.coroutine 或者其他工具将你的函数封装成一个可以返回 Promise 的广义 async function 。 并不需要等到 aysnc/await 变成 native. 将来迁移到 async/await 只需要修改这个定义的地方即可(如 bar), 调用者(如 foo)并不需要知晓你的改变。

    差异

    async funtion foo1(n){ let b = await bar(); return b + n; } let foo2 = co.wrap(function*(n){ let b = yield bar(); return b + n; }); 

    这两种形式,抛开一个是 function declaration, 一个是 variable declaration的差异,还有一点就是

    1. foo1.length // 1
    2. foo2.length // 0

    case

    https://cnodejs.org/topic/56ab1c0526d02fc6626bb383 裸奔着用 generator, 那样使用者必须使用 co, 绑死使用者是很危险的哦. see

    其他使用 promise.then.then.then.then ... 赶紧向这边迁移吧~

    其他

    个人观点,不对请指正。谢谢。

    11 条回复    2016-05-17 11:21:53 +08:00
    fds
        1/span>
    fds  
       2016-04-11 05:58:31 +08:00
    在用 TypeScript 自带的 async/await ,确实挺方便的。只是目前只支持转到 es6 ,直接喂给 node 需要手动少写些新特性的代码。
    welefen
        2
    welefen  
       2016-04-12 12:08:53 +08:00
    @fds TS 里用 async/await ,编译模式就要选 ES6 ,然后 class 等 ES6 特性就不编译了。 最后只好用 tsc + babel 编译搞定
    fds
        3
    fds  
       2016-04-12 17:15:09 +08:00
    @welefen 是啊 ES5 支持还得等等。还好 node.js 4 已经支持不少 es6 的特性啦,写后端没问题。
    fds
        4
    fds  
       2016-04-12 17:16:31 +08:00
    @welefen 现在 atom 编辑器支持 ts 的 compile on save ,加上 babel 就不方便了,所以只能妥协中
    welefen
        5
    welefen  
       2016-04-12 17:17:08 +08:00
    @fds 不过我还是喜欢使用 Babel 编译,这样就不用关心哪个版本的 Node.js 支持了哪些 ES6 特性了。
    welefen
        6
    welefen  
       2016-04-12 17:18:35 +08:00
    @fds 并且现在使用 Babel 编译还有一个好处是,有些编译后的代码性能要优于现在 V8 支持的代码(因为现在 V8 主要还是在实现 ES6 特性,还没做什么优化)
    magicdawn
        7
    magicdawn  
    OP
       2016-04-12 17:38:30 +08:00
    @fds @welefen

    其实我写这篇文章是想<del>纠正</del> generator 的使用,推荐大量用 co.wrap or bluebird.coroutine 去封装 async function 。->_->
    fds
        8
    fds  
       2016-04-13 10:41:53 +08:00
    @welefen 哦,这样呀,受教了。我当时给 babel 配 spread operator 支持时换了好几个 plugin 才能正确处理,担心有问题,就没有继续使用了。
    说到优化。我特别想吐槽下 node 的速度, v4 比 v0.10 慢了快一倍,线上同样的代码。

    @magicdawn 我是从 github.com/caolan/async 直接跳到 es7 的 async/await 的,所以自己没用过 generator ;p
    welefen
        9
    welefen  
       2016-04-13 11:38:09 +08:00
    是完全一样的代码 V4 比 v0.10 慢?

    如果项目想用 async/await 这些新特性的话,并且不像折腾编译配置的话,可以尝试下我们奇舞团开源的框架, https://thinkjs.org/
    frogcjn
        10
    frogcjn  
       2016-05-16 15:19:16 +08:00
    @welefen
    @fds

    试了一下, node 6.1.0 + express 4.13.4 + TypeScript 1.8, 输出选择 es6 , class , async func 可以共存也可以直接用。

    https://github.com/Microsoft/typescript-build2016-demos

    TypeScript 2 也快出了,支持 async func 输出到 ES5
    fds
        11
    fds  
       2016-05-17 11:21:53 +08:00
    @welefen 对,同样的代码,同样的用户量,等待时间和 cpu 占用都提高了。 github 上看也有外国人提 issue ,但不清楚是 v8 的哪个版本或者参数引起的,所以不了了之了。
    ThinkJS 不错,做 web 项目的话会考虑下。

    @frogcjn node 6 几乎完全支持 es6 啦,很好,等进入 LTS 再换。线上换版本还是比较麻烦。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2720 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 35ms UTC 14:10 PVG 22:10 LAX 06:10 JFK 09:10
    Do have faith in what you're doing.
    ubao msn 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