Подтвердить что ты не робот

Angular 1.6.0: ошибка "возможно необработанное отклонение"

У нас есть шаблон для разрешения promises в нашем 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 неожиданно жалуется на наши модульные тесты (в Карме) для отклонения promises с ошибкой "Возможно необработанное отклонение". Но мы обрабатываем отказ во второй функции, которая вызывает нашу службу ошибок.

Что именно ищет Angular здесь? Как он хочет, чтобы мы "отреагировали" на отказ?

4b9b3361

Ответ 1

Попробуйте добавить этот код в свой конфиг. Однажды у меня была аналогичная проблема, и этот обходной путь сделал трюк.

app.config(['$qProvider', function ($qProvider) {
    $qProvider.errorOnUnhandledRejections(false);
}]);

Ответ 2

Нашел проблему, вернувшись к Angular 1.5.9 и повторив тест. Это была простая проблема с вводом, но Angular 1.6.0 заменил это, выбросив вместо этого ошибку "Возможно необработанное отклонение", запутывая фактическую ошибку.

Ответ 3

Код, который вы показываете, будет обрабатывать отклонение, которое происходит до вызова .then. В такой ситуации будет вызываться второй обратный вызов, который вы передадите на .then, и будет отменен отказ.

Однако, когда обещание, по которому вы вызываете .then, успешно, оно вызывает 1-й обратный вызов. Если этот обратный вызов выдает исключение или возвращает отклоненное обещание, это результирующее отклонение не будет обрабатываться, потому что второй обратный вызов не обрабатывает отклонения по причине 1-го. Это как раз то, как обещают реализации, соответствующие спецификации Promises/A +, и Angular promises являются совместимыми.

Вы можете проиллюстрировать это следующим кодом:

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")));

Если вы запустите его в Node, который также соответствует Promises/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

Ответ 4

Первый вариант - просто скрыть ошибку при ее отключении, настроив errorOnUnhandledRejections в конфигурации $qProvider, как предложено Cengkuru Michael

НО, это приведет к отключению регистрации. Сама ошибка останется

Лучшее решение в этом случае будет: обработка отклонения с помощью метода .catch(fn):

resource.get().$promise
    .then(function (response) {})
    .catch(function (err) {});

LINKS:

Ответ 6

Я наблюдал такое же поведение во время выполнения теста. Странно, что на производственный код работает нормально и терпит неудачу только на тестах.

Простое решение, чтобы сделать ваши тесты счастливыми - добавить catch(angular.noop) к вашему обещанию. В случае примера выше он должен выглядеть так:

resourceMock.get = function () {
    var deferred = $q.defer();
    deferred.reject(error);
    return { $promise: deferred.promise.catch(angular.noop) };
};

Ответ 7

Вы можете скрыть проблему, отключив 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);
    });

Ссылка: https://github.com/angular-ui/ui-router/issues/2889