AngularJS services such as $http
, $timeout
, $resource
, etc. use the $q
service internally to generate their promises. With those services there generally is no need to inject the $q
service. In fact if you see $q.defer
being used with those services, you should be asking Is this a “Deferred Antipattern”?.
There are some methods of the $q
service that are useful in certain circumstances.
The $q.all
method is used to wait on several promises.
var promise1 = $http.get(url1);
var promise2 = $http.get(url2);
$q.all([promise1, promise2]).then( responseArray ) {
$scope.data1 = responseArray[0].data;
$scope.data2 = responseArray[1].data;
}).catch( function ( firstError ) {
console.log(firstError.status)
});
The .catch
method can be used to convert a rejected promise to a fulfilled promise. And vice versa with the .then
method. No need to use $q.defer
for that. For more information, see Angular execution order with $q
.
The $q.when
method is useful for generating a promise from unknown sources.
var promise = $q.when(ambiguousAPI(arg1));
The $q.when
method creates a $q
promise in all cases whether ambiguousAPI
returns a value, a $q
promise, or a promise from another library.
Because calling the .then
method of a promise returns a new derived promise, it is easily possible to create a chain of promises. It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain. This makes it possible to implement powerful APIs.1
To summarize: The $q
service is used to create a promise, so when using service (like $http
,$timeout
,$resource
,etc.) that already return promises you generally don't need to use the $q
service.