catch 之后执行
Executing then after catch
我有以下 fiddle:
http://jsfiddle.net/thelgevold/3uv9nnjm/6/
angular.module('hello',[]).controller('helloController',function($q){
console.clear();
function someService(){
var deferred = $q.defer();
deferred.reject({e:'error'});
return deferred.promise;
}
function callService(){
return someService().then(function(obj){
console.log('first then');
}).
catch(function(e){
console.log('error1');
var deferred = $q.defer();
deferred.reject({e:'error'});
return deferred.promise;
});
}
callService().catch(function(e){
console.log('error2');
}).then(function(e){
console.log('second then');
});
});
它本质上只是一个快速的 $q promise POC。我的问题是:为什么在拒绝承诺时调用最后一个 then 子句?输出结果如下:
错误1
错误2
第二个
我明白为什么要打印 error1/error2,但我认为第二个 then 字符串不应该被打印,因为承诺被拒绝了。我认为它会省略 "second then" ,原因与省略 "first then" 的原因相同。
有什么想法吗?
在我开始之前,请不要这样做:
var deferred = $q.defer();
deferred.reject({e:'error'});
return deferred.promise;
这样做:
return $q.reject({e:'error'});
或者最好是这样:
return $q.reject(new Error('error'));
Beware the deferred antipattern.
现在回答你的问题。
调用 callService()
后的 .catch()
正在捕获错误并且不会产生新错误。它本质上有 "handled" 错误,下面的 .then()
处理程序可以自由调用。
与您的示例等效的同步代码为:
function someService() {
throw { e: 'error' };
}
function callService() {
try {
var obj = someService();
console.log('first then');
} catch (e) {
console.log('error1');
throw { e: 'error' };
}
}
var e;
try {
e = callService();
} catch (e) {
console.log('error2');
}
console.log('second then');
我认为如果你这样看,它是非常有道理的。
Promises/A+ 规范中的相关文本是 here。出于所有意图和目的,您可以将 catch
处理程序视为与 onRejected
处理程序相同的事物:
2.2.7. then must return a promise [3.3].
promise2 = promise1.then(onFulfilled, onRejected);
2.2.7.1. If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x).
基本上,您的 onRejected
处理程序是 "returning" 值 undefined
,因此 catch()
生成的承诺解析为值 undefined
。
我有以下 fiddle: http://jsfiddle.net/thelgevold/3uv9nnjm/6/
angular.module('hello',[]).controller('helloController',function($q){
console.clear();
function someService(){
var deferred = $q.defer();
deferred.reject({e:'error'});
return deferred.promise;
}
function callService(){
return someService().then(function(obj){
console.log('first then');
}).
catch(function(e){
console.log('error1');
var deferred = $q.defer();
deferred.reject({e:'error'});
return deferred.promise;
});
}
callService().catch(function(e){
console.log('error2');
}).then(function(e){
console.log('second then');
});
});
它本质上只是一个快速的 $q promise POC。我的问题是:为什么在拒绝承诺时调用最后一个 then 子句?输出结果如下:
错误1
错误2
第二个
我明白为什么要打印 error1/error2,但我认为第二个 then 字符串不应该被打印,因为承诺被拒绝了。我认为它会省略 "second then" ,原因与省略 "first then" 的原因相同。 有什么想法吗?
在我开始之前,请不要这样做:
var deferred = $q.defer();
deferred.reject({e:'error'});
return deferred.promise;
这样做:
return $q.reject({e:'error'});
或者最好是这样:
return $q.reject(new Error('error'));
Beware the deferred antipattern.
现在回答你的问题。
调用
callService()
后的 .catch()
正在捕获错误并且不会产生新错误。它本质上有 "handled" 错误,下面的 .then()
处理程序可以自由调用。
与您的示例等效的同步代码为:
function someService() {
throw { e: 'error' };
}
function callService() {
try {
var obj = someService();
console.log('first then');
} catch (e) {
console.log('error1');
throw { e: 'error' };
}
}
var e;
try {
e = callService();
} catch (e) {
console.log('error2');
}
console.log('second then');
我认为如果你这样看,它是非常有道理的。
Promises/A+ 规范中的相关文本是 here。出于所有意图和目的,您可以将 catch
处理程序视为与 onRejected
处理程序相同的事物:
2.2.7. then must return a promise [3.3].
promise2 = promise1.then(onFulfilled, onRejected);
2.2.7.1. If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x).
基本上,您的 onRejected
处理程序是 "returning" 值 undefined
,因此 catch()
生成的承诺解析为值 undefined
。