AngularJS provides the $q
service to handle asynchronous operations using promises. Two common ways to manage multiple promises are:
$q.all()
– Used to execute multiple promises in parallel and resolve when all are complete.$q.defer()
– Creates a deferred object, allowing manual control over promise resolution.
This guide will cover:
What $q.all()
and $q.defer()
do
Differences between them
When to use each approach
Practical examples
1. What is $q.all()
?
$q.all()
is used when you need to execute multiple promises in parallel and wait for all of them to complete before proceeding.
Key Features of $q.all()
✔ Takes an array or object of promises as input.
✔ Resolves when all promises succeed or rejects if any promise fails.
✔ Useful for running multiple independent async operations.
Example: Fetching Multiple API Calls Using $q.all()
app.controller('DataCtrl', function($scope, $q, $http) {
let request1 = $http.get('/api/users');
let request2 = $http.get('/api/products');
let request3 = $http.get('/api/orders');
$q.all([request1, request2, request3]).then(function(results) {
$scope.users = results[0].data;
$scope.products = results[1].data;
$scope.orders = results[2].data;
}).catch(function(error) {
console.error("Error fetching data:", error);
});
});
Why use $q.all()
?
- Runs API requests in parallel instead of sequentially.
- Waits until all promises resolve before proceeding.
- Rejects immediately if any promise fails.
2. What is $q.defer()
?
$q.defer()
creates a deferred object that allows manual control over resolving or rejecting a promise.
Key Features of $q.defer()
✔ Provides resolve()
and reject()
methods to manually control the promise.
✔ Useful for custom promise handling, like wrapping callbacks.
✔ Can be used when we need to resolve/reject dynamically at different times.
Example: Using $q.defer()
to Wrap a Callback Function
app.factory('AuthService', function($q) {
return {
login: function(username, password) {
let deferred = $q.defer();
// Simulating async login with setTimeout
setTimeout(function() {
if (username === 'admin' && password === '1234') {
deferred.resolve("Login Successful");
} else {
deferred.reject("Invalid Credentials");
}
}, 2000);
return deferred.promise;
}
};
});
app.controller('LoginCtrl', function($scope, AuthService) {
$scope.login = function() {
AuthService.login($scope.username, $scope.password).then(function(success) {
$scope.message = success;
}).catch(function(error) {
$scope.message = error;
});
};
});
Why use $q.defer()
?
- Allows manual control over promise resolution.
- Can be useful for converting callback-based APIs into promises.
- Helps when asynchronous operations depend on external events.
3. Differences Between $q.all()
and $q.defer()
Feature | $q.all() | $q.defer() |
---|---|---|
Purpose | Runs multiple promises in parallel | Creates a manually controlled promise |
Input | Accepts an array or object of promises | Creates a single deferred object |
Resolution | Resolves when all promises succeed | Resolves when manually triggered |
Rejection | Rejects immediately if any promise fails | Manual reject with deferred.reject() |
Use Case | Fetching multiple API calls, batch processing | Wrapping callback-based functions, event-based promises |
4. When to Use $q.all()
vs $q.defer()
?
Use $q.all()
when:
✔ You have multiple promises that need to run together.
✔ You need to wait for all before continuing.
✔ Example: Fetching multiple API calls in parallel.
Use $q.defer()
when:
✔ You need manual control over promise resolution.
✔ You are wrapping a callback-based function.
✔ Example: Handling authentication, file uploads, or external events.
5. Combining $q.all()
with $q.defer()
Sometimes, we need both $q.all()
and $q.defer()
in a single use case.
Example: Using $q.all()
Inside a Deferred Function
app.factory('DataService', function($q, $http) {
return {
fetchAllData: function() {
let deferred = $q.defer();
let usersPromise = $http.get('/api/users');
let productsPromise = $http.get('/api/products');
$q.all([usersPromise, productsPromise]).then(function(results) {
deferred.resolve({
users: results[0].data,
products: results[1].data
});
}).catch(function(error) {
deferred.reject("Data fetch failed: " + error);
});
return deferred.promise;
}
};
});
🚀 Why?
$q.all()
handles multiple API calls.$q.defer()
allows a single, controlled promise for better error handling.
Conclusion
Feature | $q.all() | $q.defer() |
---|---|---|
Best for | Running multiple promises in parallel | Wrapping callbacks, manual control |
Resolution | Automatically when all promises complete | Manually with deferred.resolve() |
Rejection | Fails if any promise fails | Can reject dynamically |
Example Use Case | Fetching multiple APIs together | Handling authentication, external events |