你肯定使用的是promise机制不正确地,抛出用户定义的 throw 语句并不构成正确捕获它作为承诺拒绝。如中所述$q https://docs.angularjs.org/api/ng/service/%24q文档:
当将 deferreds/promise 与熟悉的行为进行比较时
尝试/捕捉/抛出,思考reject as the throwJavaScript 中的关键字。
这也意味着如果您通过承诺错误“捕获”错误
回调并且您希望将错误转发到派生的承诺
当前的承诺,你必须通过返回一个来“重新抛出”错误
通过拒绝构造拒绝。
它们相似但不等同,要捕获用户定义的 throw 语句,您应该使用catch
语句块。尽管$q
承诺只应catch
拒绝的承诺。因此,在您的情况下,返回被拒绝的承诺是处理流程的正确方法,而不是抛出用户定义的异常。
DEMO http://plnkr.co/edit/StJdi62SJQSBCaivbkym?p=preview
脚本语言
describe('Q Service Test', function() {
var $q,
$rootScope;
beforeEach(inject(function(_$q_, _$rootScope_) {
$q = _$q_;
$rootScope = _$rootScope_;
}));
it('Rejected promises are handled properly', function() {
var state = 'ok';
$q.when(1)
.then(function() {
return $q.reject('rejected');
})
.catch(function() {
state = 'error';
});
$rootScope.$digest();
expect(state).toBe('error');
});
});
UPDATE:
你的代码在浏览器中表现出这种行为的原因是因为 Angular 的$q
实现使用try/catch
处理 Promise 队列时的语句块。当任何回调抛出任何错误时,它会捕获错误本身,并以异常作为拒绝原因来拒绝它,然后使用$exceptionHandler
记录错误。我建议您简单地返回拒绝的承诺。
至于单元测试这样做的原因是因为angular-mocks
的实施$exceptionHandler https://docs.angularjs.org/api/ngMock/provider/%24exceptionHandlerProvider与实际应用有所不同$exceptionHandler https://docs.angularjs.org/api/ng/service/%24exceptionHandler。前者创建具有不同模式的提供程序,默认的 Angular-Mocks 实现使用rethrow
模式反过来抛出异常而不是记录它。如果您想让单元测试的行为与默认应用程序的行为相同$exceptionHandler
然后你可以将模式设置为'log'
.
DEMO http://plnkr.co/edit/gGoYcTGXglSBN12UGmGw?p=preview
脚本语言
describe('Q Service Test', function() {
var $q,
$rootScope;
beforeEach(module('ng', function($exceptionHandlerProvider) {
$exceptionHandlerProvider.mode('log');
}));
beforeEach(inject(function(_$q_, _$rootScope_) {
$q = _$q_;
$rootScope = _$rootScope_;
}));
it('Caught exceptions are handled properly', function() {
var state = 'ok';
$q.when(1)
.then(function() {
throw new Error();
})
.catch(function() {
state = 'error';
});
$rootScope.$digest();
expect(state).toBe('error');
});
});