Angulaire 1.6.0: erreur de "rejet éventuellement non manipulé" [dupliquer]
cette question a déjà une réponse ici:
nous avons un modèle pour résoudre des promesses dans notre application angulaire 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 à 1.6.0, Angular se plaint soudainement dans nos tests unitaires (en Karma) pour des promesses rejetées avec une erreur de" rejet éventuellement non manipulé". Mais nous gérons le rejet dans la deuxième fonction qui appelle notre service d'erreur.
que cherche exactement Angular ici? Comment veut-il qu'on" gère " le rejet?
11 réponses
essayez d'ajouter ce code à votre configuration. J'ai eu un problème similaire une fois, et cette solution a fait l'affaire.
app.config(['$qProvider', function ($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}]);
le code que vous affichez traitera un rejet qui se produit avant l'appel à .then
. Dans une telle situation, le 2ème rappel que vous passez à .then
sera appelé, et le rejet seront traitées.
cependant , lorsque la promesse sur laquelle vous appelez .then
est réussie, il appelle le premier rappel. si ce callback lance une exception ou renvoie une promesse rejetée, ce rejet résultant ne sera pas traité , parce que le 2e rappel ne gère pas les rejets en cause au 1er. C'est exactement comme cela que les implémentations de promesse conformes au travail de spécification Promises/a+ et les promesses angulaires sont conformes.
vous pouvez l'illustrer 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 aussi 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
a trouvé le problème en retournant à L'angle 1.5.9 et en relançant l'essai. Il s'agissait d'une simple question d'injection, mais le point 1.6.0 anguleux a remplacé cette erreur par une erreur de rejet "possiblement Non manipulé", ce qui a masqué l'erreur réelle.
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 n'éteindra que la journalisation. L'erreur elle-même restera
la meilleure solution dans ce cas sera - traitement d'un rejet avec .catch(fn)
méthode:
resource.get().$promise
.then(function (response) {})
.catch(function (err) {});
LINKS:
s'il vous Plaît vérifier la réponse ici:
rejet possiblement non freiné dans L'angle 1,6
cette valeur a été fixée à 316f60f et le correctif est inclus dans le v1.6.1 release .
j'ai observé le même comportement pendant l'exécution du test. Il est étrange que sur le code de production fonctionne bien et échoue seulement sur les tests.
la solution facile pour rendre vos tests heureux est d'ajouter catch(angular.noop)
à votre mock promesse. Dans le cas de 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) };
};
vous pouvez masquer le problème en désactivant les rejets erroronunhandled, mais l'erreur dit que vous avez besoin de" gérer un rejet possible " donc vous avez juste besoin d'ajouter une prise à votre promesse.
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);
});
référence: https://github.com/angular-ui/ui-router/issues/2889
j'étais également face à la même question après la mise à jour à L'angle 1.6.7 mais quand j'ai regardé dans le code, erreur a été jeté pour $interval.cancel(interval);
pour mon cas
mon problème a été résolu une fois que j'ai mis à jour angular-mocks
à la dernière version(1.7.0).
pour éviter d'avoir à taper .catch(function () {})
dans votre code à plusieurs endroits, vous pouvez ajouter un decorator
au $exceptionHandler
.
C'est une option verbose que les autres, mais vous n'avez qu'à faire le changement dans un seul 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);
};
}
};
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 j'obtenais le dictionnaire local de façon asynchrone. Le problème était que le fichier json qu'il recevait était incorrectement indenté (mélange des espaces et des onglets). La requête de L'EEG n'a pas échoué.
Correction de l'indentation résolu le problème.
j'ai eu ce même avis apparaître après avoir fait quelques changements. Il s'est avéré que c'était parce que j'avais changé entre une seule requête $http
et plusieurs requêtes utilisant le service $q
d'angularjs.
Je ne les avais pas enveloppés dans un tableau. par exemple
$q.all(request1, request2).then(...)
plutôt que
$q.all([request1, request2]).then(...)
j'espère que cela pourrait sauver quelqu'un un certain temps.