天天看点

Promise 反模式

promises are about making asynchronous code retain most of the lost properties of synchronous code such as flat indentation and one exception channel. – bluebird wiki: promise anti patterns

promises 是为了让异步代码也能保持这些同步代码的属性:扁平缩进和单异常管道。

这种反模式中,<code>deferred</code> 对象的创建是没有意义的,反而会增加代码的复杂度。

例如:

这里的 <code>deferred</code> 对象并没有什么意义,而且可能在出错的情况下无法捕获。

正确的写法应该为:

再举一个例子:

这就像重复造轮子,因为回调 api 的封装应该使用 promise 库的 promisification(promise 化)方法实现:

通用 promise 化可能更快,因为可以借助 promise 的内部操作,还能处理一些极端情况:例如 <code>libraryfunction</code> 同步抛异常或者用到了多个成功值。

必须用的时候。

当要封装的回调 api 和规范不一致时,例如 <code>settimeout</code>:

这样使用 <code>.then</code> 就像下面这段代码:

正常的同步写法是:

所以正确的 <code>.then</code> 用法应该是:

如果只是想对两个 promise 的结果做处理,可以使用 promise.all 方法:

这里的问题在于加入 <code>somethingcomplicated()</code> 出错的话不会被捕获。promise 应该链式调用。也就是说所有的 <code>then</code> 方法都应该返回一个新的 <code>promise</code>。所以上面代码的正确写法为:

例如需要对一个集合中的每个元素执行异步操作:

这里的问题在于需要遍历数组,其实可以用 <code>promise.all</code> 解决:

最容易犯的错误,没有使用 <code>catch</code> 去捕获 <code>then</code> 里抛出的报错:

这里的问题在于 snippet2 在 function resolve 中出错时无法捕获。而 catch 则可以。

下面的两个示例返回结果是不一样的:

example2 改变了返回值,因而 result 发生了变化。

<code>async flow control, event loop, callback, promises, generators, async/wait, coroutines</code>

promises 所做的承诺是保证异步代码顺序执行,并能够链式管理异常和错误。相比使用<code>event loop</code> 和回调(callback)来控制异步代码的顺序执行,promises 能够让代码更加清晰易懂。generator 更是从语言级别上提供了更好的支持。

v8 有两个编译器:通用编译器和优化编译器。也就是v8 中的 javascript 代码总是被编译成机器码后才执行的。

例如 <code>a + b</code> 编译成汇编代码为:

但如果 <code>a</code> 和 <code>b</code> 都是整数的话,则会被编译成:

这样编译后的代码性能会快很多,因为跳过了 javascript 对不同类型数据相加的处理。

通用编译器会得到前一种汇编码,优化编译器会得到后一种汇编码。两种汇编代码性能很容易产生 100 倍的差异。但是存在一些模式,这些模式下的代码优化编译器不会去处理(称为<code>bail out</code>)。promises 属于一种被 bail out 的模式。

python greenlets(基于gevent)

go coroutine

<a href="https://github.com/petkaantonov/bluebird/wiki/promise-anti-patterns#the-thensuccess-fail-anti-pattern" target="_blank">bluebird wiki</a>

<a href="http://taoofcode.net/promise-anti-patterns/" target="_blank">tao of code</a>

<a href="https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html" target="_blank">https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html</a>

<a href="https://www.promisejs.org/patterns/" target="_blank">https://www.promisejs.org/patterns/</a>

<a href="http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript" target="_blank">http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript</a>

<a href="https://github.com/nodejs/node/wiki/async-exception-handling" target="_blank">node.js async exception handling</a>

<a href="https://promise-nuggets.github.io/" target="_blank">promise nuggets</a>

<a href="https://github.com/petkaantonov/bluebird/wiki/optimization-killers" target="_blank">optimization killers</a>

<a href="https://github.com/vhf/v8-bailout-reasons" target="_blank">v8 bailout reasons</a>

<a href="https://sdiehl.github.io/gevent-tutorial/" target="_blank">python greenlets</a>

转载自:http://taobaofed.org/blog/2016/05/03/promise-anti-patterns/

作者:云翮

继续阅读