- 编辑 -
我最近遇到了一些关于承诺的奇怪的事情,但我想这可能是因为它违背了承诺的哲学。
考虑以下代码:
// Assuming Auth is just a simple lib doing http requests with promises
Auth.signup()
.then(succCall, errCall)
.then(loginSucc, loginErr)
// My callbacks here
function succCall (){
// OK, send second promise
console.log('succCall');
return Auth.login();
}
function errCall(){
// I do some things here and now
// I want to break out from here
console.log('errCall');
}
function loginSucc(){
// This is the callback of the login method when it went OK
// I want to enter here ONLY if with go through the succCall
console.log('loginSucc');
}
function loginErr(){
// This is the callback of the login method when it went not ok
// I want to enter here ONLY if with go through the succCall
console.log('loginErr');
}
如果Auth.signup()出现问题,这就是show:
如果我在errCall中执行$ q.reject(),则会发生以下情况:
这就是我想要的:
现在问题是,当注册出错时,它会进入errCall,这很好,但是它会进入loginSucc ......
我想在遇到任何errorCallback(这里是errCall或loginErr)时突破当时的链。
- 编辑 -
我认为我被某种意思误解了,如果出现问题,我想完全打破连锁而不检查任何其他“然后”。
好像我在说:如果先错了就停在这里,如果先是然后确定继续,如果第二个“然后”确定继续,如果第三个“然后”错了,停止
// Just like if i did the following but by chainning "then" methods
// My callbacks here
function succCall (){
// OK, send second promise
return Auth.login().then(loginSucc, loginErr);
}
我的观点是,如果我有很多“然后”链接
,我不想只有一个错误处理程序答案 0 :(得分:2)
errCall
函数需要返回一个promise,并且需要拒绝该promise以解除loginErr。
function errCall(){
// i do some things here and now
return $q(function(resolve, reject) {
// auto reject
reject();
});
}
或者尝试.catch
:
Auth.signup()
.then(succCall)
.then(loginSucc)
.catch(function(err){
// caught error, problem is you won't know which function errored out, so you'll need to look at the error response
});
答案 1 :(得分:2)
实际发生的是:
try {
try {
var a = succCall();
} catch(e1) {
a = errCall(e1);
}
var b = loginSucc(a);
} catch(e2) {
b = loginErr(e2);
}
您可以通过调用
来突破链return $q.reject('Reason Err was called');
在errCall()
函数中。
修改强>
正如OP通过调用$q.reject
所述,代码将进入loginErr
函数。
或者,您可以像这样修改代码:
Auth.signup()
.then(function(a) {
succCall()
return loginSucc(a).then(null, loginErr);
}, errCall)
您可以在这两个问题中阅读更多内容:
答案 2 :(得分:1)
只是不要将任何errCall
或loginErr
传递给then
并在promise链的末尾使用catch()
,它会在第一次出错时被中断,将传递给catch()
。如果您希望明确处理Auth.signup()
错误,那么您的errCall
应如下所示:
function (err) {
if(isFatal(err)) {
return Promise.reject(new Error('Fatal!')); //`catch()` handler will be called with `new Error('Fatal!')`
} else {
return 'something'; //next `then()` handler will be called with 'something'
}
}
答案 3 :(得分:0)
您最好的选择是返回一个永远不会从errCall()
解决的承诺:
function errCall() {
console.log('errCall');
return $q.defer().promise;
}
但你是对的,你要做的是“反对承诺的哲学”。
在评估第一个承诺期间发生错误时,调用loginSucc
函数当然是一个问题。但是,可以通过在其他人已经指出的errCall
中再次拒绝来解决这个问题。但是你不应该试图避免执行loginErr
,否则你的代码在概念上是错误的。
表达式的评估
Auth.signup().then(succCall, errCall)
产生另一个承诺。合同是承诺有一个then()
方法,将两个回调作为参数,一个用于成功,一个用于失败。合同还包括成功评估promise并在所有其他情况下调用错误/失败回调时调用成功回调。 如果您打算永远不打电话给任何一方,请不要使用承诺!