I do it like Bradley Braithwaite suggests in his blog:
app
.factory('searchService', ['$q', '$http', function($q, $http) {
var service = {};
service.search = function search(query) {
// We make use of Angular's $q library to create the deferred instance
var deferred = $q.defer();
$http
.get('http://localhost/v1?=q' + query)
.success(function(data) {
// The promise is resolved once the HTTP call is successful.
deferred.resolve(data);
})
.error(function(reason) {
// The promise is rejected if there is an error with the HTTP call.
deferred.reject(reason);
});
// The promise is returned to the caller
return deferred.promise;
};
return service;
}])
.controller('SearchController', ['$scope', 'searchService', function($scope, searchService) {
// The search service returns a promise API
searchService
.search($scope.query)
.then(function(data) {
// This is set when the promise is resolved.
$scope.results = data;
})
.catch(function(reason) {
// This is set in the event of an error.
$scope.error = 'There has been an error: ' + reason;
});
}])
Key Points:
The resolve function links to the .then function in our controller i.e. all is well, so we can keep our promise and resolve it.
The reject function links to the .catch function in our controller i.e. something went wrong, so we can’t keep our promise and need to
reject it.
It is quite stable and safe and if you have other conditions to reject the promise you can always filter your data in the success function and call deferred.reject(anotherReason)
with the reason of the rejection.
As Ryan Vice suggested in the comments, this may not be seen as useful unless you fiddle a bit with the response, so to speak.
Because success
and error
are deprecated since 1.4 maybe it is better to use the regular promise methods then
and catch
and transform the response within those methods and return the promise of that transformed response.
I am showing the same example with both approaches and a third in-between approach:
success
and error
approach (success
and error
return a promise of an HTTP response, so we need the help of $q
to return a promise of data):
function search(query) {
// We make use of Angular's $q library to create the deferred instance
var deferred = $q.defer();
$http.get('http://localhost/v1?=q' + query)
.success(function(data,status) {
// The promise is resolved once the HTTP call is successful.
deferred.resolve(data);
})
.error(function(reason,status) {
// The promise is rejected if there is an error with the HTTP call.
if(reason.error){
deferred.reject({text:reason.error, status:status});
}else{
//if we don't get any answers the proxy/api will probably be down
deferred.reject({text:'whatever', status:500});
}
});
// The promise is returned to the caller
return deferred.promise;
};
then
and catch
approach (this is a bit more difficult to test, because of the throw):
function search(query) {
var promise=$http.get('http://localhost/v1?=q' + query)
.then(function (response) {
// The promise is resolved once the HTTP call is successful.
return response.data;
},function(reason) {
// The promise is rejected if there is an error with the HTTP call.
if(reason.statusText){
throw reason;
}else{
//if we don't get any answers the proxy/api will probably be down
throw {statusText:'Call error', status:500};
}
});
return promise;
}
There is a halfway solution though (this way you can avoid the throw
and anyway you'll probably need to use $q
to mock the promise behavior in your tests):
function search(query) {
// We make use of Angular's $q library to create the deferred instance
var deferred = $q.defer();
$http.get('http://localhost/v1?=q' + query)
.then(function (response) {
// The promise is resolved once the HTTP call is successful.
deferred.resolve(response.data);
},function(reason) {
// The promise is rejected if there is an error with the HTTP call.
if(reason.statusText){
deferred.reject(reason);
}else{
//if we don't get any answers the proxy/api will probably be down
deferred.reject({statusText:'Call error', status:500});
}
});
// The promise is returned to the caller
return deferred.promise;
}
Any kind of comments or corrections are welcome.
success()
,error()
andfinally()
combined withcatch()
? Or do I have to usethen(successFunction, errorFunction).catch(exceotionHandling).then(cleanUp);
– Roentgenoscope