我如何使用Bluebirderror handling程序?

介绍

这个问题的目的是最终解决我在Bluebird开发中遇到的一个问题。 不过,我也借此机会澄清了一些事情,所以会有一些问题。 我也会提前道歉,在阅读故事的过程中,您可能会感受到任何混乱或无聊的感觉。


问题

据我的理解,蓝鸟试图聪明地捕捉到被忽略的拒绝,根据以下策略:

第二种方法,默认情况下是蓝鸟,如果拒绝未被第二回合开始处理,则调用注册处理程序。 – Bluebird自述文件#error handling

现在这里是第一个问题: “第二个回合的开始”是什么意思?

在同一部分的后面,logging如下:

当然,这不是完美的,如果你的代码由于某种原因需要猛扑一下,并且在承诺挂了一段时间之后附加了error handling函数,那么你会看到恼人的消息。 在这种情况下,您可以使用.done()方法来指示应该抛出任何悬挂exception。 – Bluebird自述文件#error handling

现在,我相信我碰到了上面描述的情况,我的用例如下:

  • 我调用一个函数,它将为我提供附加.catch()的承诺:

     lib.loadUrls() .catch(function(e){console.log(e);}); 
  • 在内部,该函数从URL1加载内容并基于内容,依次从URL2加载内容:

     lib.loadUrls = return this.loadUrl1() .then(this.loadUrl2.bind(this)) 
  • 如果在这个链中的第二个承诺被拒绝,错误首先由catch处理,然后由Bluebirds处理,也Possibly unhandled error处理程序。

这最后一个行为是不需要的,我不明白为什么这样做。 所以问题二可能是: 为什么,尽pipe附加和执行error handling程序,蓝鸟仍然认为错误的可能性是“未处理”?

我在想,很明显,在拒绝传播给.catch()的时候,这个承诺“一直悬而未决”。 在这种情况下,我应该通过“使用.done() ”来解决它(根据引用的文档)。

现在,我已经尝试了几件事情,但是我不太清楚如何在这个场景中“使用.done”。 (这没有帮助.done()返回undefined,阻止我从.finally -ing。)

所以这就介绍了我的第三个和第四个问题: 在这种情况下如何使用.done()以及如何明确地结束承诺链,但仍然附加.finally()

编辑1:我创build了一些JSFiddles重现该错误:

  • 使用蓝鸟1.0.5重现了错误。
  • 使用最新的Bluebird.js再现了这个bug(在这个时候)
  • 使用Beta版本0.10.0-1 不会重现该错误。

编辑2:开发人员修复了这个错误。

这确实只是蓝鸟的一个回归bug,现在已经修复了。

关于需要使用.done()一点是非常理论化的,你不会在实践中运行的情况下,你需要附加error handling程序,这样会导致错误肯定报告。

这很可能是蓝鸟的错误,因为处理错误不应该被报告(假设你正确地处理承诺loadUrls正文)。 所以可能你应该把它报告给Bluebird问题跟踪器。

关于done ,它是纯粹的访问函数,如果使用,而不是then使用,或者只是在处理parsing值时catch

把它当作第一selectfunction, then使用,并且只有当你真的需要转换到其他许诺时才能被catch ,这种方法你也不需要依靠错误的错误监视(最好把它彻底关掉)。

在你的情况下done应该用作:

 lib.loadUrls().done(); // eventual error will be thrown 

如果由于某种原因,你想专门处理错误(例如,在运行服务器,你不希望它抛出):

 lib.loadUrls().done(null, function (error) { // handle error }); 

编辑:

只是注意到,你还是要处理由lib.loadUrls().catch(..)返回的lib.loadUrls().catch(..) 。 在这种情况下, done不是一个解决scheme。 done只能作为最终的调用,但是你可以把它与finally结合如下:

 lib.loadUrls().finally(function () { // cleanup }).done();