In the following code snippet error 1
and success 2
will be logged. How can I can I propagate error callbacks being invoked rather than the success callbacks being invoked if the original deferred is rejected.
angular.module("Foo", []);
angular
.module("Foo")
.controller("Bar", function ($q) {
var deferred = $q.defer();
deferred.reject();
deferred.promise
.then(
/*success*/function () { console.log("success 1"); },
/*error*/function () { console.log("error 1"); })
.then(
/*success*/function () { console.log("success 2"); },
/*error*/function () { console.log("error 2"); });
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="Foo">
<div ng-controller="Bar"></div>
</div>
Error is propagate by returning $q.reject
in the error callback
var deferred = $q.defer();
deferred.reject();
deferred.promise
.then(
/*success*/function () { console.log("success 1"); },
/*error*/function () { console.log("error 1"); return $q.reject('error 1')})
.then(
/*success*/function () { console.log("success 2"); },
/*error*/function () { console.log("error 2"); });
});
think of success/failure as try/catch
try{
var val = dummyPromise();
} catch (e){
val = "SomeValue";
}
if catch does not throws an exception, it is considered that the error is handled and hence outer calling function does not sees the error which occured in inner function.
Similar stuff happening here, you have to return return $q.reject();
from a promise in order for the next promise in the chain to fail too. See example plunker: http://plnkr.co/edit/porOG8qVg2GkeddzVHu3?p=preview
The reason is: Your error handler may take action to correct the error. In your error-function your dealing with the error,if not specified otherwise, it will return a new promise which is resolved. Therefore it is not reasonable to have the next promise failing by default (try-catch analogy).
By the way, you can return $q.reject()
even from a success handler, if you sense an error condition, to have the next promise in the chain failing.
You're catching the error and handling it - so it gets to the success handler. If you want to reject it, you have to do it by returning $q.reject();
To sum the comments up, to propagate errors in the promise chain, either:
1) Do not provide an errorCallback
for then
:
deferred.promise
.then(
/*success*/function () { console.log("success 1"); },
.then(
/*success*/function () { console.log("success 2"); },
/*error*/function () { console.log("error 2"); }); // gets called
Or
2) Return $q.reject()
from the errorCallback
:
deferred.promise
.then(
/*success*/function () { console.log("success 1"); },
/*error*/function (err) { console.log("error 1"); return $q.reject(err); });
.then(
/*success*/function () { console.log("success 2"); },
/*error*/function () { console.log("error 2"); }); // gets called
From the angular $q.reject documentation:
This api should be used to forward rejection in a chain of promises.
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