We have a pattern for resolving promises in our Angular app that has served us well up until 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);
});
And here is how we are triggering the error in Karma:
resourceMock.get = function () {
var deferred = $q.defer();
deferred.reject(error);
return { $promise: deferred.promise };
};
Now, with the update to 1.6.0, Angular is suddenly complaining in our unit tests (in Karma) for rejected promises with a "Possibly unhandled rejection" error. But we are handling the rejection in the second function that calls our error service.
What exactly is Angular looking for here? How does it want us to "handle" the rejection?
Try adding this code to your config. I had a similar issue once, and this workaround did the trick.
app.config(['$qProvider', function ($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}]);
The code you show will handle a rejection that occurs before the call to .then
. In such situation, the 2nd callback you pass to .then
will be called, and the rejection will be handled.
However, when the promise on which you call .then
is successful, it calls the 1st callback. If this callback throws an exception or returns a rejected promise, this resulting rejection will not be handled, because the 2nd callback does not handle rejections in cause by the 1st. This is just how promise implementations compliant with the Promises/A+ specification work, and Angular promises are compliant.
You can illustrate this with the following code:
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")));
If you run it in Node, which also conforms to Promises/A+, you get:
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
The first option is simply to hide an error with disabling it by configuring errorOnUnhandledRejections
in $qProvider configuration as suggested Cengkuru Michael
BUT this will only switch off logging. The error itself will remain
The better solution in this case will be - handling a rejection with .catch(fn)
method:
resource.get().$promise
.then(function (response) {})
.catch(function (err) {});
LINKS:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With