这个问题旨在最终解决我在与Bluebird开发中遇到的问题。但是,我也利用这个机会澄清了一些事情,所以会有副问题。我也提前道歉,因为在阅读未来的故事时你可能会遇到任何混乱或无聊的感觉。
据我的理解,Bluebird试图根据以下策略智能地捕捉被忽略的拒绝:
第二种方法,即蓝鸟默认采用的方法是,如果在第二轮开始时未处理拒绝,则调用已注册的处理程序。 - Bluebird Readme # Error Handling
现在,这是第一个侧面问题:“第二轮的开始”是什么意思?
稍后在同一部分中,记录了以下内容:
当然这并不完美,如果你的代码由于某种原因需要突然进入并且在承诺已经搁置一段时间后将错误处理程序附加到某些承诺那么你会看到烦人的消息。在这种情况下,您可以使用.done()方法来表示应该抛出任何挂起的异常。 - Bluebird Readme # Error Handling
现在,我相信我的用例如下所述:
我调用了一个函数,它将为我提供.catch()
附加的承诺:
lib.loadUrls()
.catch(function(e){console.log(e);});
在内部,该函数从URL1加载内容,并根据内容,按顺序从URL2加载内容:
lib.loadUrls =
return this.loadUrl1()
.then(this.loadUrl2.bind(this))
如果此链中的第二个承诺被拒绝,则错误由catch first 处理,然后由Bluebirds Possibly unhandled error
处理程序处理。
这最后一个行为是不受欢迎的,我无法弄清楚它为什么会这样做。问题二可能是:为什么,尽管附加并执行了错误处理程序,Bluebird是否仍然会考虑错误被“未处理”的可能性?
我在想,当拒绝传播到.catch()
时,显然承诺“已经暂停了一段时间”。在这种情况下,我应该通过“使用.done()
”来解决它(根据引用的文档)。
现在,我已经尝试了几件事,但在这种情况下我无法弄清楚如何“使用.done”。 (.done()
返回undefined没有帮助,阻止我进入.finally
- 。
所以这引入了我的第三个和第四个问题:如何在此方案中使用.done()
,和如何明确缔结承诺链,但仍然附加.finally()
编辑1:我创建了一些JSFiddles来重现错误:
编辑2: dev fixed错误。
答案 0 :(得分:4)
这确实只是蓝鸟中的一个回归错误,现在已修复。
关于需要使用.done()
的一点是理论上的,你不会在实际情况下运行,你需要以一种会导致误报的方式附加错误处理程序。
答案 1 :(得分:1)
最有可能是Bluebird错误,因为处理错误不应报告(假设您正确处理loadUrls
正文中的承诺)。所以你可能应该把它报告给Bluebird问题跟踪器。
关于done
,如果您只是处理已解决的值,那么它是纯粹的访问函数(如果使用的话,而不是then
或catch
。
将done
视为首选函数并使用then
和catch
只有在您确实需要转换为其他承诺时才是好的,使用这种方法您也不需要依赖关于越野车错误监控(最好将其完全关闭)。
在您的情况下done
应该用作:
lib.loadUrls().done(); // eventual error will be thrown
如果出于某种原因你想要专门处理错误(例如在运行服务器时你不想抛出),请执行:
lib.loadUrls().done(null, function (error) {
// handle error
});
编辑:
注意,您仍然希望处理lib.loadUrls().catch(..)
与finally
返回的承诺。在这种情况下,done
不是解决方案。 done
应仅用作最终通话,但您可以将其与finally
结合使用,如下所示:
lib.loadUrls().finally(function () {
// cleanup
}).done();