ES6--浅析Promise内部结构 (7)

这种方式看起来有些山寨,它也确实解决了问题。但它引入的一个新问题就是链式调用后面的所有回调函数都无法被垃圾回收器回收(在一个靠谱的实现里,Promise应该在执行完所有回调后删除对所有回调函数的引用以让它们能被回收,在前文的实现里,为了减少复杂度,并没有做这种处理),但如果我们不使用匿名函数,而是使用函数定义或者函数变量的话,在需要多次执行的Promise链中,这些函数也都只有一份在内存中,不被回收也是可以接受的。

将返回一个什么也不做的Promise封装成一个有语义的函数,以增加代码的可读性

Promise.cancel = Promise.stop = function() { return new Promise(function(){}) }

这么使用了:

new Promise(function(resolve, reject) { resolve(42) }) .then(function(value) { // "Big ERROR!!!" return Promise.stop() }) .catch() .then() .then() .catch() .then()

 

3、promise的链上返回的最后一个promise出错了怎么办?

new Promise(function(resolve) { resolve(42) }) .then(function(value) { alter(value) })

但运行这段代码的话你会发现什么现象也不会发生,既不会alert出42,也不会在控制台报错,怎么回事呢。细看最后一行,`alert`被打成了`alter`,那为什么控制台也没有报错呢,因为`alter`所在的函数是被包在`try/catch`块里的,`alter`这个变量找不到就直接抛错了,这个错就正好成了then返回的Promise的rejection reason。

解决办法:

(1)所有的promise链的最后都加上一个catch,这样出错后就会被捕获到,这样违背了DRY原则,而且繁琐;

(2)借鉴Q的一个方法done,把这个方法加到promise链的最后,就能够处理捕获最后一个promise出现的错误,其实个catch的思路一样,这个是框架来实现的。

(3)在一个Promise被reject的时候检查这个Promise的onRejectedCallback数组,如果它为空,则说明它的错误将没有函数处理,这个时候,我们需要把错误输出到控制台,让开发者可以发现。

在Promise被reject但又没有callback时,把错误输出到控制台。

 

4、出错时,使用throw new Error()还是使用return Promise.reject(new Error())呢?

从性能和编码的舒适角度考虑:

(1)性能方面:throw new Error()会使代码进入catch块里的逻辑(我们把多有的回调都包在try/catch里),传说throw多了会影响性能,因为一旦throw,代码就有可能跳转到不可预知的位置。

而使用promise.reject(new Error()),则需要构造一个新的promise对象(包含2个数组,4个函数:resolve/reject,onResolved/onRejected),也会花费一定的时间和内存。因为onResolved/onRejected函数是直接被包在promise实现里的try里,出错后直接进入到这个try对应的catch块,代码的跳跃幅度相对较小,性能应该可以忽略不记。

(2)编码的舒适度方面:出错用throw,正常用return,正常可以明显的区分出错和正常

综上觉得还是promise里发现显式错误后,用throw抛出错误比较好,而不是显式的构造一个呗reject的promise对象。

 

七、实践

注意:

1、不要把promise写成嵌套的结构

// 错误的写法 promise1.then(function(value) { promise1.then(function(value) { promise1.then(function(value) { }) }) })

2、链式promise要返回一个promise,而不是构造一个promise

// 错误的写法 Promise.resolve(1).then(function(){ Promise.resolve(2) }).then(function(){ Promise.resolve(3) })

 

八、参考

https://github.com/xieranmaya/blog/issues/3

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxdwg.html