How can I ensure that the complete()
function will run regardless of the outcome of the $http call using the promise API provided with Angular.js?
$http({
method: 'POST',
url: submitUrl,
data: $scope.data
})
.success(function(data) {
// execute this code on success
})
.error(function(data) {
// execute this code on error
})
.complete(function() {
// execute this code regardless of outcome
});
One could use this to hide an AJAX spinner icon once the request is complete. You would want to hide the spinner regardless of the request outcome.
I'm not the world's greatest expert in Angular.js but understand you can do as follows :
whatever.then(function() {
// success code here
}, function() {
// error code here
return true; // return anything that's not undefined (and not a `throw()`) to force the chain down the success path at the following then().
}).then(function() {
// "complete" code here
});
You are essentially forced to contrive something from one or more .then()
, which is a $q promise's only method.
It depends on what you would like to do, but for clean-up logic and similar you may also use finally()
to run either on fulfillment or rejection of your promise:
promise.finally(function () {
// Do something regardless of outcome.
});
Please note that although finally()
is supported by $q
(and some other libraries) is not part of the official draft.
If you don't care if the request is successful or not, then you can pass the same callback to success
and error
...
var cb = function(response){
// do something
};
$http.post(submitUrl, $scope.data).success(cb).error(cb);
// OR
$http.post(submitUrl, $scope.data).then(cb, cb);
But be aware that success
and error
callbacks have a different signature than the then
callbacks.
- http://docs.angularjs.org/api/ng.$http
- http://docs.angularjs.org/api/ng.$q
Also, promises are recognized by the templating engine in angular, which means that in templates you can treat promises attached to a scope as if they were the resulting values.
This means that you can do this:
Controller:
$scope.article = $http.get('/articles/' + articleId);
Template:
<article ng-cloak>
<h3>{{article.title}}</h3>
<div>{{article.content}}</div>
</article>
And the view will update when the $http.get
promise has been resolved.