Угловой 1.6.0:" возможно необработанный отказ " ошибка [дубликат]
На этот вопрос уже есть ответ здесь:
У нас есть шаблон для разрешения обещаний в нашем приложении Angular, который хорошо служил нам вплоть до Angular 1.6.0:
resource.get().$promise
.then(function (response) {
// do something with the response
}, function (error) {
// pass the error the the error service
return errorService.handleError(error);
});
И вот как мы запускаем ошибку в карме:
resourceMock.get = function () {
var deferred = $q.defer();
deferred.reject(error);
return { $promise: deferred.promise };
};
Теперь, с обновлением до 1.6.0, Angular-это внезапно жалуемся в наших модульных тестах (в карме) на отвергнутые обещания с ошибкой "возможно необработанный отказ". Но мы обрабатываем отклонение во второй функции, которая вызывает нашу службу ошибок.
Что именно ищет здесь Angular? Как он хочет, чтобы мы "справились" с отказом?
11 ответов:
Попробуйте добавить этот код в свою конфигурацию. Однажды у меня была подобная проблема, и этот обходной путь сделал свое дело.
app.config(['$qProvider', function ($qProvider) { $qProvider.errorOnUnhandledRejections(false); }]);
Код, который вы показываете, будет обрабатывать отклонение, которое происходит до вызова
.then
. В такой ситуации будет вызван 2-й обратный вызов, который вы передаете.then
, и отклонение будет обработано.однако , когда обещание, по которому вы звоните
.then
, успешно, оно вызывает 1-й обратный вызов. Если этот обратный вызов вызывает исключение или возвращает отклоненное обещание, это результирующее отклонение не будет обработано , потому что 2-й обратный вызов не обрабатывает отклонения в причине 1. именно так работают реализации promise, совместимые со спецификациейPromises/A+, и угловые обещания совместимы.Вы можете проиллюстрировать это следующим кодом:
function handle(p) { p.then( () => { // This is never caught. throw new Error("bar"); }, (err) => { console.log("rejected with", err); }); } handle(Promise.resolve(1)); // We do catch this rejection. handle(Promise.reject(new Error("foo")));
Если вы запустите его в узле, который также соответствует обещаниям/A+, вы получите:
rejected with Error: foo at Object.<anonymous> (/tmp/t10/test.js:12:23) at Module._compile (module.js:570:32) at Object.Module._extensions..js (module.js:579:10) at Module.load (module.js:487:32) at tryModuleLoad (module.js:446:12) at Function.Module._load (module.js:438:3) at Module.runMain (module.js:604:10) at run (bootstrap_node.js:394:7) at startup (bootstrap_node.js:149:9) at bootstrap_node.js:509:3 (node:17426) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: bar
Нашел проблему, откатившись назад к угловой 1.5.9 и повторно запустив тест. Это была простая проблема инъекции, но Angular 1.6.0 заменил ее, выбросив вместо этого ошибку "возможно необработанный отказ", запутывая фактическую ошибку.
Первый вариант-просто скрыть ошибку, отключив ее, настроив
errorOnUnhandledRejections
в конфигурации $qProvider, как предложеноCengkuru Michael
Но это только отключит ведение журнала. Сама ошибка останется
Лучшим решением в этом случае будет-обработка отказа с помощью метода
.catch(fn)
:resource.get().$promise .then(function (response) {}) .catch(function (err) {});
Ссылки:
Пожалуйста, проверьте ответ здесь:
Возможно необработанное отклонение в угловом 1.6
Это было исправлено с помощью 316f60f , и исправление включено в выпуск v1.6.1.
Я наблюдал такое же поведение во время выполнения теста. Странно, что на производстве код работает нормально и проваливается только на тестах.
Простое решение, чтобы сделать ваши тесты счастливыми, это добавить
catch(angular.noop)
к вашему обещанию mock. В случае примера выше это должно выглядеть так:
resourceMock.get = function () { var deferred = $q.defer(); deferred.reject(error); return { $promise: deferred.promise.catch(angular.noop) }; };
Вы можете замаскировать проблему, отключив errorOnUnhandledRejections, но ошибка говорит, что вам нужно "обработать возможный отказ", поэтому вам просто нужно добавить уловку к своему обещанию.
resource.get().$promise .then(function (response) { // do something with the response }).catch(function (error)) { // pass the error the the error service return errorService.handleError(error); });
Я также столкнулся с той же проблемой после обновления до Angular 1.6.7, но когда я заглянул в код, ошибка была выброшена для
$interval.cancel(interval);
для моего случаяМоя проблема была решена, как только я обновил
angular-mocks
до последней версии (1.7.0).
Чтобы избежать необходимости вводить дополнительные
Это более подробный вариант, чем другие, но вам нужно только внести изменения в одном месте..catch(function () {})
в коде в нескольких местах, вы можете добавитьdecorator
к$exceptionHandler
.angular .module('app') .config(configDecorators); configDecorators.$inject = ["$provide"]; function configDecorators($provide) { $provide.decorator("$exceptionHandler", exceptionHandler); exceptionHandler.$inject = ['$delegate', '$injector']; function exceptionHandler($delegate, $injector) { return function (exception, cause) { if ((exception.toString().toLowerCase()).includes("Possibly unhandled rejection".toLowerCase())) { console.log(exception); /* optional to log the "Possibly unhandled rejection" */ return; } $delegate(exception, cause); }; } };
Возможно, это не ваша специфическая ситуация, но у меня была похожая проблема.
В моем случае я использовал angular-i18n и получал словарь локали асинхронно. Проблема заключалась в том, что файл json, который он получал, был неправильно отступлен (смешивание пробелов и вкладок). Запрос получить не удалось.
Исправление отступа решило проблему.
У меня было такое же уведомление, появившееся после внесения некоторых изменений. Это оказалось потому, что я переключился с одного запроса
$http
на несколько запросов, используя сервис angularjs$q
.Я не упаковал их в массив. например
$q.all(request1, request2).then(...)
Вместо
Я надеюсь, что это может сэкономить кому-то немного времени.$q.all([request1, request2]).then(...)