Promise 反模式

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 是为了让异步代码也能保持这些同步代码的属性:扁平缩进和单异常管道。

Deferred 反模式

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

例如:

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

正确的写法应该为:

再举一个例子:

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

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

什么时候使用 deferred?

必须用的时候。

当要封装的回调 API 和规范不一致时,例如 setTimeout

.then(success, fail) 反模式

这样使用 .then 就像下面这段代码:

正常的同步写法是:

所以正确的 .then 用法应该是:

嵌套 Promise

例如:

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

断链

例如:

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

集合

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

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

总结

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

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

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

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

更多关键词

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

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

V8 优化

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

例如 a + b 编译成汇编代码为:

但如果 ab 都是整数的话,则会被编译成:

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

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

他山之石

Python greenlets(基于gevent)

go coroutine

参考资料

2 2 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部