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

情况2:没有被失败回调捕获,抛出错误最终会变成异常

read('./1.txt','utf8') .then((data)=>{ throw new Error('出错了') })

情况3:如果没有被失败的回调捕获,那么最终会被catch捕获到

read('./1.txt','utf8') .then((data)=>{ throw new Error('出错了') }) .then((data)=>{ }) .catch((err)=>{ console.log(err) // Error:出错了 报错 })

情况4:如果被失败的回调捕获,那么就不会被catch捕获到

read('./1.txt','utf8') .then((data)=>{ throw new Error('出错了') }) .then(null,(err)=>{ console.log(err) // Error:出错了 报错 }) .catch((err)=>{ console.log(err) // 不会执行到这里 })

(5)catch是错误没有处理的情况下才会执行

(6)then回调中可以不写

 

六、关于promise的其他问题

1、性能问题

可能各位看官会觉得奇怪,Promise能有什么性能问题呢?并没有大量的计算啊,几乎都是处理逻辑的代码。

理论上说,不能叫做“性能问题”,而只是有可能出现的延迟问题。什么意思呢,记得刚刚我们说需要把4块代码包在setTimeout里吧,先考虑如下代码:

var start = +new Date() function foo() { setTimeout(function() { console.log('setTimeout') if((+new Date) - start < 1000) { foo() } }) } foo()

运行上面的代码,会打印出多少次'setTimeout'呢,各位可以自己试一下,不出意外的话,应该是250次左右,我刚刚运行了一次,是241次。这说明,上述代码中两次setTimeout运行的时间间隔约是4ms(另外,setInterval也是一样的),实事上,这正是浏览器两次Event Loop之间的时间间隔,相关标准各位可以自行查阅。另外,在Node中,这个时间间隔跟浏览器不一样,经过我的测试,是1ms。

单单一个4ms的延迟可能在一般的web应用中并不会有什么问题,但是考虑极端情况,我们有20个Promise链式调用,加上代码运行的时间,那么这个链式调用的第一行代码跟最后一行代码的运行很可能会超过100ms,如果这之间没有对UI有任何更新的话,虽然本质上没有什么性能问题,但可能会造成一定的卡顿或者闪烁,虽然在web应用中这种情形并不常见,但是在Node应用中,确实是有可能出现这样的case的,所以一个能够应用于生产环境的实现有必要把这个延迟消除掉。在Node中,我们可以调用process.nextTick或者setImmediate(Q就是这么做的),在浏览器中具体如何做,已经超出了本文的讨论范围,总的来说,就是我们需要实现一个函数,行为跟setTimeout一样,但它需要异步且尽早的调用所有已经加入队列的函数,这里有一个实现。

 

2、如何停止一个promise链?

在一些场景里,我们会遇到一个较长的promise的链式调用,在某一步出现的错误让我们没有必要去运行链式调用后面所有的代码,类似于下面这样的(此处省略then/catch里的函数):

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

假设这个`Big ERROR!!!`的出现让我们完全没有必要运行后面所有的代码了,但链式调用的后面即有catch,也有then,无论我们是`return`还是`throw`,都不可避免的会进入某一个`catch`或`then`里面,那有没有办法让这个链式调用在`Big ERROR!!!`的后面就停掉,完全不去执行链式调用后面所有回调函数呢?

从一个实现者的角度看问题时,确实找到了答案,就是在发生`Big ERROR`后return一个Promise,但这个Promise的executor函数什么也不做,这就意味着这个Promise将永远处于`pending`状态,由于then返回的Promise会直接取这个永远处于`pending`状态的Promise的状态,于是返回的这个Promise也将一直处于`pending`状态,后面的代码也就一直不会执行了,具体代码如下:

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

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

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