1
leecade 2015-05-17 19:08:59 +08:00
敢用
|
2
magicdawn 2015-05-17 19:33:18 +08:00
深入浅出node.js上有教简单实现!
|
3
ysmood OP @magicdawn 我这个跟书上的不一样,一般书上的实现是跑不过那 800 多个单测的,我这个 80 行的是可以的,我这个可能更偏向工程实际些。对于想更深入了解的人可能有帮助。
|
4
laoyur 2015-05-17 19:44:38 +08:00 via Android
mark,关注下
楼主能贴一下跟bluebird的性能比较就更好了 |
5
ysmood OP @laoyur readme 里已经有个和各个库的性能比较了,看那个表格,其中有 Bluebird,你甚至能自己跑下 benchmark,具体怎么运行 readme 里也有。不过更复杂情况的性能测试不是当前的开发重点,性能会之后慢慢优化。
|
6
otakustay 2015-05-17 21:05:42 +08:00
我们也撸了一个Promise库,与楼主共同分享相互学习下
https://github.com/ecomfe/promise 测试都是过Promise/A+的一个样,unhandledRejection错误处理也有,大小上大概这样 ~ coffee -c -p yaku/src/yaku.coffee | uglifyjs | gzip -c | wc -c 2064 ~ cat promise/src/*.js | uglifyjs | gzip -c | wc -c 2754 我们的库加了2个功能,第一是enhance.js增加了一些便携的方法,比如thenBind、thenGetProperty。第二是setImmediate作了setImmediate函数的shim来让异步更快,去掉这2个的话 ~ cat promise/src//Promise.js promise/src//PromiseCapacity.js promise/src/main.js promise/src/then.js promise/src/util.js promise/src/hook.js | uglifyjs | gzip -c | wc -c 1799 我们现在在考虑的是: 1. 这样的库与原生的Promise的关系如何处理 2. 全局错误处理应该怎么做 3. Promise的cancel/abort应该怎么做 与楼主共同学习 |
7
ysmood OP @otakustay 我这边除了 unhandled rejection,还有 long stack trace,这个也非常重要。另外你可以测下你的性能和我的差别。
我的这个库的目的就是不添加除了调试用的任何非原生接口,换句话说用我这个库,可以没有任何副作用的删除它,切换到使用原生的 Promise。 关于 cancel/abort 这个不是 Promise 应该解决的问题,ES6 的 community 已经应该讨论过这个问题了。 |
8
ysmood OP @otakustay 另外你理解的 unhandled reject 似乎不对。比如我用你的库运行
Promise.reject(10).catch(function() {}) 结果还是会打印 10,这不符合 ES6 spec 的规范。 |
9
otakustay 2015-05-17 22:50:16 +08:00
@ysmood
我特地去找了一下,unhandled reject在ES6中还没有定义,我想不同的人会有不同的理解,跟着BlueBird走可能是个不错的选择,但最终会如何暂时还不知道。我们确实使用了更为同步的方式略过reject到catch的这个过程,这是我们从性能上考虑的设计了 cancel/abort的问题现在还在讨论中,并没有被废弃吧,在ES7中会不会实现我是很期待的,事实上除开Promise,几乎各种语言中的异步库或者协程功能都会涉及到cancellation的功能,早晚都是逃不开的话题,特别是在SPA会越来越大行其道的当前前端环境下,没有cancellation功能的异步会很不好用 性能上我试了下,其实你的性能应该是劣势的,特别在没有setImmediate的环境下做密集测试,但不同机器也可能会有不同的结果…… 最后,目的其实不一样,我们更希望除了shim之外,可以再做一些什么方便基于Promise的开发,如ES6范围内的Promise没有finally的功能,这是一个很大的缺憾,让不少的代码变成.then(foo, foo)并且不能使用匿名函数,略不方便。因此也拿出来和楼主的共同学习参考 |
11
otakustay 2015-05-17 23:11:59 +08:00
@ysmood 我转了一圈回来,感觉在Chrome上支持async stack是很有必要的,但Node上的long stack我打算放弃,如果一个库的定位是原生Promise的shim的话,node 0.12已经自带Promise了,对于这种版本可控的环境来说我们就不打算再继续为其提供shim了
所以还是和你的思路有差异化:) |
12
ysmood OP @laoyur 所以这里为了问题的简化,只讨论 ES6,unhandled reject 这个我口误,是要符合现行 chrome 或者 firefox的处理方式,他们会在 gc 里处理它,我这边尽量模拟了这个过程,这很关键。
关于性能,我帮你跑了下,在 node 下差距很大: Node v1.8.1 OS darwin Arch x64 CPU Intel(R) Core(TM) i7-4850HQ CPU @ 2.30GHz -------------------------------------------------------------------------------- yaku total: 324ms init: 215ms resolution: 109ms memory: rss - 115mb | heapTotal - 96mb | heapUsed - 76mb pp total: 2378ms init: 1940ms resolution: 438ms memory: rss - 300mb | heapTotal - 278mb | heapUsed - 252mb 浏览器里没必要测性能,只有服务端 server 用 yaku 的时候这才是瓶颈,用户的 browser 里不可能跑重运算的。 |
13
ysmood OP @laoyur 除了 shim 外的功能应该基于一个基础库开发。比如我会把 yaku 写到完善,然后基于它写个 yaku-ex 之类的,人们可以选择最适合需求的,而不是一股脑都放一起。
关于类似 finally 这种我很早就在 stackoverflow 上讨论过了,ES6 大概不会支持的见: http://stackoverflow.com/questions/26667598/will-javascript-es6-promise-support-done-api 你可以很容易在类似 yaku-ex 这样的库里实现一个。 |
14
ysmood OP @laoyur 你这个在 node 下已经慢到跟 q(2755ms) 差不多了,Bluebird 最快 301ms,上面的测试越小越快。
|
15
ysmood OP @laoyur 而且类似这种单测也和原生 Promise 都不一致:
new Promise(function () { throw 10 }).catch(function() {}) 其实不是把 promises-aplus-tests 都跑过就万事大吉了,还是有很多浏览器的规范在里面的。 |
17
phoenixlzx 2015-05-17 23:48:08 +08:00 1
给 ys 菊苣点赞
star 已送 |
18
otakustay 2015-05-18 00:08:04 +08:00
@ysmood 从一开始就没有打算让这样的Promise库在node中跑,所以node的性能对我的意义不大,原因很简单,node现在支持原生Promise所以没有使用的场景,我还是不怎么理解什么时候能在node中使用一个Promise shim库,因为node无法升级使用较新版本吗,无法使用较新node的时候又能引入一个第三方库吗……在我厂似乎还真没有这样的情况(考虑到node可以直接把binary做portable带上)
关于finally的支持你可以去esdiscuss.org找,基本上会在ES7来添加这个API,纯粹因为讨论时ES6已经进入RC没办法再添加方法了 确实我相信还存在一些(不少)的边界场景有BUG,也必然会不断跟进,多谢你提供的case,如果你有更全面的case不如我们合作来补充aplus-test? |
19
ysmood OP @otakustay 我这个库就在你厂的一些项目跑着呢。我 readme 第一句话就是说比原生的快,这就是 node 使用它的理由。比如此时此刻你厂用的一个门户级网站就是就是用的 node 0.8,你部门不代表你厂,不代表现实复杂世界吧?
|
20
otakustay 2015-05-18 00:23:50 +08:00
|
21
ysmood OP @otakustay 抱歉,话说的可能重了点,就是论事而已。
题外话,可以试着自动生成文档。打个硬广吧,可以用我写的 nokit 自动生成文档,yaku就是用它生成的 readme。好玩的是 nokit 也依赖了 yaku。nokit 这个用于替代 gulp,更好用。看看 yaku 怎么用 nokit 的就行了。 |
22
otakustay 2015-05-18 00:43:10 +08:00
@ysmood 这个好,nokit以前确实没听过,去看看
老实说,有兴趣的话,真的一起补一下aplus-test吧,那东西有多不全其实我们都是知道的,更别说这货在浏览器里跑用上browserify也会有点小问题,被折腾了蛮久…… |
23
ysmood OP @otakustay 我不打算入 aplus-test 的坑了,我另有计划,我打算把 Bluebird 的 test suite 抽离出来,它的单测应该是业界比较可信的,是实践的结果。
|
24
coolicer 2015-05-18 08:23:28 +08:00
es6 原生自带的啊
|
27
coolicer 2015-05-18 10:59:11 +08:00
打错字,之类,不是之后。
|
28
iwege 2015-05-18 11:09:22 +08:00
bluebird 对catch的加强实际用起来的时候很赞。另外建议helper 可以做插件用户自己require。
|
29
ysmood OP @coolicer 我读过 babeljs 用的 core-js 来实现 Promise,这个实现很大,我刚测了最新的 babel,编译之后 minify 了也有 20KB,太大了,而且也不支持 unhandled rejection 和 long stack trace。性能也没看到有太多优化:
Node v1.8.1 OS darwin Arch x64 CPU Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz -------------------------------------------------------------------------------- yaku total: 234ms init: 155ms resolution: 79ms memory: rss - 115mb | heapTotal - 96mb | heapUsed - 76mb babel-runtime total: 770ms init: 527ms resolution: 243ms memory: rss - 190mb | heapTotal - 172mb | heapUsed - 150mb 比 yaku 慢了接近 3 倍 |
30
ysmood OP @iwege 对 catch 已经有所加强了,但还有很多可优化空间,之后有时间会进一步加强。helper 这个我不是很理解,能具体解释下吗?
|
31
iwege 2015-05-18 12:43:46 +08:00
@ysmood
API 模块化,类似lodash,想要用到哪个就用添加哪个。 Bluebird的catch是可以针对特定类型Error进行相关的处理,这个的方法比较简单也避免了自己去写if else的判断,代码可读性比不用要高很多。 |
32
coolicer 2015-05-18 13:25:31 +08:00
重新看了帖子,项目还是好。能不能换个名字,让它跟promise沾边,我个人很怕用那些奇怪名字,因为不认识。像bluebird,起码也是个单词,好吧,都是无关重要的观点。
|
33
ysmood OP @lwege 了解了,可以加到扩展里去,但基础库不会有这个功能。当时我就是被 bluebird error 的这层 wrap 恶心到过,才想自己写个库的,它这么干会和原生写法不兼容。
要扩展加个 xcatch 之类的就行了,比如你 new error 的时候,用库提供的些标准 error 类型,这时就能用 xcatch 到指定 type 的 error。 关于 lodash 模块话 API 这个确实可以做,多谢提醒~ |
34
ysmood OP @coolicer 一开始就在 FAQ 里说了名字的问题,就是怕这样的吐槽,这名字其实就是 promise 的意思,只是换了一个语言而已,否则取名字太困难了,好的名字都被别人抢了。
|
35
coolicer 2015-05-21 08:43:46 +08:00
老是跟youku联想起来 = =
|