web-dev-qa-db-fra.com

Angular 1.6.0: erreur "Rejet éventuellement non pris en charge"

Nous avons un modèle de résolution de promesses dans notre application Angular qui nous a bien servi jusqu'à 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);
        });

Et voici comment nous déclenchons l'erreur dans Karma:

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

Maintenant, avec la mise à jour vers la version 1.6.0, Angular se plaint soudain dans nos tests unitaires (en karma) des promesses rejetées avec une erreur "Rejet éventuellement non géré". Mais nous traitons le rejet dans la deuxième fonction qui appelle notre service d’erreur.

Que recherche exactement Angular ici? Comment veut-il que nous "gérions" le rejet?

66
Groucho

Essayez d'ajouter ce code à votre configuration. J'ai eu un problème similaire une fois, et cette solution de contournement a fait l'affaire.

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

Le code que vous montrez gérera un rejet qui se produit avant l'appel à .then. Dans une telle situation, le deuxième rappel que vous passez à .then sera appelé et le rejet sera traité.

Cependant , lorsque la promesse sur laquelle vous appelez .then réussit, le premier rappel est appelé. Si ce rappel lève une exception ou retourne une promesse refusée, le rejet résultant ne sera pas traité , car le deuxième rappel ne gérera pas les refus en raison du 1er C’est ainsi que les implémentations de promesse conformes à la spécification Promises/A + et à Angular promesses sont conformes.

Vous pouvez illustrer cela avec le code suivant:

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

Si vous l'exécutez dans Node, qui est également conforme à Promises/A +, vous obtenez:

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
21
Louis

Résoudre le problème en revenant à Angular 1.5.9 et en réexécutant le test. Il s’agissait d’un problème d’injection simple, mais Angular 1.6.0 l’a remplacé en générant à la place l’erreur "Rejet éventuellement non géré", masquant ainsi l’erreur réelle.

18
Groucho

La première option consiste simplement à masquer une erreur en la désactivant en configurant errorOnUnhandledRejections dans la configuration $ qProvider comme suggéré Cengkuru Michael

MAIS, cela ne fera que désactiver la journalisation. L'erreur elle-même restera

La meilleure solution dans ce cas sera - gérer un rejet avec la méthode .catch(fn):

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

LIENS:

16
Andrii Verbytskyi

Pour éviter d'avoir à taper .catch(function () {}) supplémentaire dans votre code à plusieurs endroits, vous pouvez ajouter un decorator au $exceptionHandler.

C’est une option plus détaillée que les autres, mais vous n’avez qu’à effectuer le changement à un endroit.

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);
        };
    }
};
5
Urielzen

Veuillez vérifier la réponse ici:

Rejet éventuellement non traité dans Angular 1.6

Ce problème a été résolu avec 16f60f et le correctif est inclus dans la version version 1.6.1 .

3
Piotr Pradzynski

Vous pouvez masquer le problème en désactivant errorOnUnhandledRejections, mais l'erreur indique que vous devez "gérer un éventuel rejet", il vous suffit donc d'ajouter un verrou à votre promesse.

resource.get().$promise
    .then(function (response) {
    // do something with the response
    }).catch(function (error)) {
        // pass the error to the error service
        return errorService.handleError(error);
    });

Référence: https://github.com/angular-ui/ui-router/issues/2889

3
giselleghadyani

J'ai observé le même comportement lors de l'exécution du test. Il est étrange que le code de production fonctionne correctement et échoue uniquement lors des tests.

La solution facile pour rendre vos tests heureux consiste à ajouter catch(angular.noop) à votre maquette de promesse. Dans l'exemple ci-dessus, il devrait ressembler à ceci:

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

J'étais également confronté au même problème après la mise à jour vers Angular 1.6.7, mais lorsque j'ai examiné le code, une erreur s'est produite pour $interval.cancel(interval); pour mon cas.

Mon problème a été résolu une fois que j'ai mis à jour angular-mocks vers la dernière version (1.7.0).

2
Dilip

Ce n'est peut-être pas votre situation particulière, mais j'ai eu un problème similaire.

Dans mon cas, j'utilisais angular-i18n et obtenais le dictionnaire de paramètres régionaux de manière asynchrone. Le problème était que le fichier json qu'il obtenait était mal mis en retrait (mélange d'espaces et de tabulations). La requête GET n'a pas échoué.

Corriger l'indentation a résolu le problème.

0
monstercode

J'ai eu cette même notification apparaît après avoir apporté quelques modifications. Il s’est avéré que c’est parce que j’avais changé entre une seule demande $http à plusieurs demandes utilisant le service angularjs $q.

Je ne les avais pas emballés dans un tableau. par exemple.

$q.all(request1, request2).then(...) 

plutôt que

$q.all([request1, request2]).then(...)

J'espère que cela permettra à quelqu'un de gagner du temps.

0
JamesEddyEdwards