Javascript 承诺链的第一个函数中$q的角度处理异常
考虑以下代码:Javascript 承诺链的第一个函数中$q的角度处理异常,javascript,angularjs,promise,Javascript,Angularjs,Promise,考虑以下代码: // Fiddle - http://jsfiddle.net/EFpn8/3/ f1().then(function(data) { console.log("success 1: "+data) return f2(); }) .then(function(data) {console.log("success 2: "+data)}) .c
// Fiddle - http://jsfiddle.net/EFpn8/3/
f1().then(function(data) {
console.log("success 1: "+data)
return f2();
})
.then(function(data) {console.log("success 2: "+data)})
.catch(function(data) {console.log("error: "+data)});
function f1() {
var deferred = $q.defer();
// An exception thrown here is not caught in catch
// throw "err";
deferred.resolve("done f1");
return deferred.promise;
}
function f2() {
var deferred = $q.defer();
// An exception thrown here is handled properly
// throw "err";
deferred.resolve("done f2");
return deferred.promise;
}
如果以下代码在f2中异常运行,则正确调用catch函数。但是,如果在f1中出现异常,那么catch代码永远不会执行,只会发生标准的JS异常
在原始Q库中,这可以通过以下代码处理:
// Fiddle - http://jsfiddle.net/FEPc7/
Q.fcall(f1).then(function(data) {
console.log("success 1: "+data)
return f2();
})
.then(function(data) {console.log("success 2: "+data)})
.catch(function(data) {console.log("error: "+data)});
使用fcall可以安全地保护f1功能,其中的异常将按预期触发catch功能
由于来自承诺链所有成员的相同行为似乎对开发人员都有帮助和自然,因此我为AngularJS创建了以下函数:
// Fiddle - http://jsfiddle.net/EFpn8/5/
function promise(work) {
var deferred = $q.defer();
try {
deferred.resolve(work());
} catch(err) {
deferred.reject(err);
throw err;
}
return deferred.promise;
}
可以这样使用:
promise(f1).then(function(data) {
console.log("success 1: "+data)
return f2();
})
.then(function(data) {console.log("success 2: "+data)})
.catch(function(data) {console.log("error: "+data)});
这很好,但是,它似乎是一个黑客。有没有什么东西可以替代呢?或者出于某种原因它是不必要的?链的第一次调用是同步的,因此乍一看,链中引发的异常随后被传递到
$q
以调用错误回调,这是针对异步承诺拒绝(或者实际上是异常)的
引自
Q比$Q有更多的特性
因此,缺少fCall
功能听起来像是团队决定可以删除的事情之一。看起来你真的得像以前一样自己滚。您可能希望使用像from这样的技术来装饰$q
和fCall
方法,因此您可以像这样使用它:
$q.fCall(f1).then(function()...
我知道这是一个较老的问题,但我今天碰到了同样的问题,找到了这个答案,但我认为我不需要添加fCall()来实现这一点。 经过一点挖掘,我发现这可以在今天的Angular v1.5中完成(不确定这在什么时候生效):
@BenjaminGruenbaum-那不是一个复制品。这些是完全不同的问题,尽管它们重复使用相同的代码:)即使您
返回$q.reject
而不是throw
?f1还不在promise代码中,因此它会同步抛出。考虑在一个承诺中包装它,或者使用另一个问题的ESAILIJA的建议。你的意思是在代码的第一行有调用<代码>承诺(F1)< /代码>吗?它应该是f1()
?@MichalCharemza-很好!感谢githib——这是一项伟大的技术,谢谢!
$q.when().then(() => f1)...