违背承诺”;那么“;带有错误的链回调
Break out of a Promise "then" chain with errorCallback
--编辑--
我最近遇到了一件关于承诺的奇怪事情,但我想这可能是因为它违背了承诺的哲学。
考虑以下代码:
// 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()出现问题,这就是显示的内容:
- errCall,loginSucc
如果我在errCall中执行$q.request(),则会发生以下情况:
- errCall,loginErr
这就是我想要的:
- errCall。。。完成,在这里停下来
现在,问题是,当注册出错时,它会进入errCall,这很好,但随后它会进入loginSucc。。。
当遇到任何错误回调(这里是errCall或loginErr)时,我想跳出then链。
--编辑--
我想我被误解了,如果出了问题,我想完全打破链条,不检查任何其他"然后"。
就好像我在说:如果第一个然后是错误的,在这里停止,如果第一个,然后可以继续,如果第二个"然后"可以继续,"如果第三个"然后"错误,停止
// 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);
}
我的观点是,如果我有许多"然后"链接的
实际发生的是:
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)
你可以在这两个SO问题中阅读更多:
- 打破承诺链
- 打破当时的承诺Angularjs
这也是一个有用的阅读:压扁承诺链
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
});
只要不将任何errCall
或loginErr
传递给then
,并在承诺链的末尾使用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'
}
}
您的最佳选择是返回从未从errCall()
:解决的承诺
function errCall() {
console.log('errCall');
return $q.defer().promise;
}
但你是对的,你试图做的是"违背承诺的哲学"。
为什么你不应该这么做
当然,当在评估第一个promise的过程中发生错误时,调用loginSucc
函数是一个问题。然而,正如其他人已经指出的那样,这可以通过在errCall
中再次拒绝来解决。但是您不应该试图避免执行loginErr
,否则您的代码在概念上会出现问题。
表达的评价
Auth.signup().then(succCall, errCall)
产生另一个承诺。约定是promise有一个then()
方法,该方法将两个回调作为参数,一个用于成功,另一个用于失败。合同还规定,在成功评估promise时调用成功回调,在所有其他情况下调用错误/失败回调如果你打算永远不打电话给他们中的任何一个,就不要用承诺
- 测试Angular Service解决错误回调中的promise
- $http服务未触发成功或错误回调
- jQuery AJAX错误回调未运行
- JavaScriptajax请求servlet调用错误回调函数
- 为什么 AJAX 完成和错误回调都触发了
- Cordova Android短信插件不会触发成功或错误回调
- 无法识别错误回调
- 在第一次错误回调时退出承诺链
- 如何获取 Ember 组件对象内部承诺成功或错误回调
- 在 Node.js 中传播错误回调,并避免所有额外的麻烦
- 在 HTTP 错误回调中访问“this”
- 在 AngularJS 中声明一个承诺,并带有命名的成功/错误回调
- 谷歌浏览器中的地理位置错误回调
- PhoneGap 3.0.0 Tanelih 蓝牙插件在 Android 上已启用错误回调不起作用
- 关闭离子侧菜单时是否有任何回调
- $http错误回调不能与 httpProvider responseInterceptor 结合使用
- JayData 上的默认错误回调
- 错误回调中的错误:TestPlugin2 = 引用错误:找不到变量:在 file:///android_asset/ww
- 是否有猫鼬连接错误回调
- 当Yii添加类错误时,是否有函数回调可用