我有一个复杂的承诺链,每个成功处理程序然后进行更多的API调用并将结果传递给下一个,依此类推。
我的情况是,根据情况,我可能会选择停止连锁。
因此,简而言之,我的代码看起来像;
API.callGeneric(/* some params here */)
.$promise
.then(success(res) {
if (processFurther(res)) {
return API.callGeneric(res).$promise;
} else {
return someFunction(res); // so that the stuff inside the next successhandler still happens
}
}, failHandler)
.then(success(res) {
// do some stuff with res
// do some important stuff independent of res (announce app ready, etc.)
}, failHandler)
因此,无论我是否选择从另一个API调用或仅仅是一个对象返回promise,都需要在最后一步中发生一些事情。
怎么办呢?
答案 0 :(得分:2)
在@BenjaminGruenbaum的帮助下解决了这个问题。
所以,基本上,我需要最后一个.then的successHandler来执行 - 至少它的一部分并不依赖于链中早先传递的承诺。
解决这个问题的方法是使用.finally
,但有一个问题。无论您决定拒绝承诺并打破链条,.finally
都会执行。在我的场景中,这不是我需要的。在.finally
中,我需要宣布我的webapp已准备好(通过websocket)到服务器和其他客户端。但如果第一个API调用本身必须被拒绝,那就不太理想了。
解决这个问题的方法是通过承诺链保持一定程度的进度,以便finally
中的处理程序完全了解已经取得了多大进展。如果这超出了我的应用程序宣布准备的某个限制,我忽略了最后的承诺拒绝。
所以基本上,解决方案现在看起来像这样;
var progress = 0;
API.callGeneric(/* some params */).$promise
.then(successOne(res) {
progress++;
return API.callGeneric(res).$promise;
}, handleErr)
.then(successTwo(res) {
progress++;
if (isResPositive(res)) {
return API.callGeneric(res).$promise;
} else {
var def = $q.defer();
def.reject(res);
return def.promise;
}
}, handleErr)
.then(/* similar stuff */)
/* etc */
.finally(function () {
if (progress > limit) {
// do stuff here
} else {
// failure, don't do stuff
}
});
答案 1 :(得分:0)
您可以使用拒绝承诺(如$q.reject(reason)
作为函数的返回值。
.then(function () {
return $q.reject()
}).then(function () {
console.log('never happens');
}).catch(function () {
console.log('you are going here because of the reject above');
}).finally(function () {
console.log('always happens');
});
请查看the documentation以获取更多信息。