Ответ 1
Вы определенно используете механизм обещаний неправильно, бросая определяемый пользователем оператор throw, не означает, что он будет ловить его как отказ от обещаний. Как указано в документации $q
:
При сравнении отложенных / promises с привычным поведением try/catch/throw, подумайте отклонить как ключевое слово throw в JavaScript. Это также означает, что если вы "поймаете" ошибку с помощью ошибки обещания обратный вызов, и вы хотите переслать ошибку на обещание, полученное из текущее обещание, вы должны "перебросить" ошибку, вернув отклонение, построенное с помощью отклонения.
Они похожи, но не эквивалентны, чтобы поймать пользовательские инструкции throw, вы должны использовать блоки операторов catch
. Пока $q
promises должен отклонить catch
promises. Таким образом, в вашем случае возврат отклоненного обещания - это правильный способ обработки процесса, а не выбрасывание пользовательского исключения.
JAVASCRIPT
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
при обработке очереди обещаний. Когда какой-либо из обратных вызовов вызывает какие-либо ошибки, он сам обнаруживает ошибку, отклоняет ее с исключением в качестве причины для отклонения, а затем использует $exceptionHandler
для регистрации ошибки. Я рекомендую вам просто вернуть отклоненное обещание.
В связи с тем, почему модульные тесты действуют таким образом, из-за angular-mocks
реализация $exceptionHandler
отличается от фактическое приложение $exceptionHandler
. Первый создает поставщика с различными режимами, реализация по умолчанию angular -mocks использует режим rethrow
, который, в свою очередь, генерирует исключение вместо его регистрации. Если вы хотите, чтобы ваши модульные тесты ведут себя так же, как и приложение по умолчанию $exceptionHandler
, вы можете установить режим 'log'
.
JAVASCRIPT
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');
});
});