js Gurus,
我在nodejs(实际上是iojs)中编写了一个解析器,我有一个典型的使用promises处理的doom回调金字塔。占据我70%时间的问题是在承诺中发现错误。
function parseHomeData(home, web) {
var deferred = Q.defer();
var homepage = web.url(home).then(function () {
// any error here dies silently
parser.getHomeInfo(homepage).then(function (parsedHome) {
console.log(parsedHome);
deferred.resolve(parsedHome);
}, function (err) {
console.log(err);
throw new Error(err);
});
}, function (err) {
console.log(err);
});
return deferred.promise;
};
如果我取消注释"这里的任何错误都会无声地死亡"它会做的。唯一的办法,就是在try / catch块里面包装,但即使在那里我只能console.log(错误)抛出新错误不起作用。是否可以通过自动故障选项运行iojs? 谢谢
答案 0 :(得分:2)
承诺捕获异常并将其变为拒绝。因此,如果您在.then()
处理程序中并且抛出异常,那么将生成与返回被拒绝的承诺相同的结果。这就是承诺的工作方式。
因此,为了使您的代码有效,您只需要返回web.url()
正在创建的实际承诺。这也将摆脱你不必要地创造承诺的一些反模式。
function parseHomeData(home, web) {
return web.url(home).then(function () {
// any exception error here becomes the rejected promise
return parser.getHomeInfo(homepage).then(function (parsedHome) {
console.log(parsedHome);
return parsedHome;
}, function (err) {
// this handler is only needed if you need the console.log(err) here
console.log(err);
throw new Error(err);
});
}, function (err) {
// this handler is only needed if you need the console.log(err) here
console.log(err);
throw err;
});
};
事实上,如果没有console.log()
语句,代码可能只会崩溃到这个:
function parseHomeData(home, web) {
return web.url(home).then(parser.getHomeInfo.bind(parser));
}
此代码块结合了以下几个方面:
返回web.url()
承诺,如果因任何原因被拒绝(例如在.then()
处理程序中抛出,则会从parseHomeData()
作为拒绝的承诺返回功能。
如果您已经拥有可以返回的Q承诺,则无需创建自己的Q承诺。
实施上述第1)项和第2项后,您可以在resolve()
处理程序中返回或抛出而不是reject()
和.then()
。
您可以在这些参考文献中阅读有关承诺反模式的更多信息:
Promise Anti-patterns (Bluebird github)