简介
这个问题旨在最终解决我在与Bluebird开发中遇到的问题 . 但是,我也利用这个机会澄清了一些事情,所以会有副问题 . 我也提前道歉,因为在阅读未来的故事时你可能会遇到任何混乱或无聊的感觉 .
问题
据我所知,Bluebird试图根据以下策略智能地捕捉被忽略的拒绝:
第二种方法,即蓝鸟默认采用的方法是,如果在第二轮开始时未处理拒绝,则调用已注册的处理程序 . - Bluebird自述文件#错误处理
现在这里是第一个侧面问题: What does "the start of a second turn" mean?
稍后在同一部分中,记录以下内容:
当然这并不完美,如果你的代码出于某种原因需要突然进入并将错误处理程序附加到某些承诺之后,承诺已经暂停了一段时间,那么你会看到恼人的消息 . 在这种情况下,您可以使用.done()方法来表示应该抛出任何挂起的异常 . - Bluebird自述文件#错误处理
现在,我相信我遇到了上述情况,我的用例如下:
- 我调用了一个函数,它将为我提供我附加
.catch()
的承诺:
lib.loadUrls()
.catch(function(e){console.log(e);});
- 在内部,该函数从URL1加载内容并根据内容,按顺序从URL2加载内容:
lib.loadUrls =
return this.loadUrl1()
.then(this.loadUrl2.bind(this))
- 如果此链中的第二个promise被拒绝,则首先由catch处理错误,然后由Bluebirds
Possibly unhandled error
处理程序处理 .
这最后一个行为是不需要的,我无法弄清楚它为什么这样做 . 问题二可能是: Why, despite an error handler being attached and executed, does Bluebird still consider the possibility of the error being "unhandled"?
我在想,显然是拒绝传播到 .catch()
时的承诺"has been hanging around for a while" . 在这种情况下,我应该通过“使用 .done()
”解决它(根据引用的文档) .
现在,我在这个场景中很清楚如何"use the .done" . ( .done()
返回undefined没有帮助,阻止了我 .finally
-ing . )
所以这介绍了我的第三个和第四个问题: How do I use .done() in this scenario, 和 how do I explicitly conclude a promise-chain, but still attach a .finally()
EDIT 1: 我创建了一些JSFiddles来重现这个bug:
-
Using Bluebird 1.0.5重现该错误 .
-
Using the latest Bluebird.js再现错误(此时)
-
Using Beta version 0.10.0-1 does not 重现该错误 .
EDIT 2: 开发fixed这个bug .
2 回答
这确实只是蓝鸟中的回归错误,现在已修复 .
关于需要使用
.done()
的一点是理论上的,你不会在实际情况下运行,你需要以一种会导致误报的方式附加错误处理程序 .这很可能是Bluebird错误,因为不应该报告处理错误(假设你在
loadUrls
正文中正确处理了promises) . 所以你可能应该把它报告给Bluebird问题跟踪器 .关于
done
,如果您只是处理已解决的值,那么's pure access function that'最好用于代替then
或catch
.将
done
视为首选函数并使用then
和catch
只有在真正需要转换到其他承诺时才是好的,使用这种方法您也不需要依赖错误监控(最好将其完全关闭) .在您的情况下
done
应该用作:如果由于某种原因你想要专门处理错误(例如在运行服务器时你不想抛出它):
编辑:
刚刚注意到,您仍然希望处理
lib.loadUrls().catch(..)
与finally
返回的承诺 . 在这种情况下done
不是解决方案 .done
应仅用作最终调用,但您可以将其与finally
组合,如下所示: