我如何使用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();