$q.all() vs $q.defer() for handling multiple promises

Loading

AngularJS provides the $q service to handle asynchronous operations using promises. Two common ways to manage multiple promises are:

  1. $q.all() – Used to execute multiple promises in parallel and resolve when all are complete.
  2. $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()
PurposeRuns multiple promises in parallelCreates a manually controlled promise
InputAccepts an array or object of promisesCreates a single deferred object
ResolutionResolves when all promises succeedResolves when manually triggered
RejectionRejects immediately if any promise failsManual reject with deferred.reject()
Use CaseFetching multiple API calls, batch processingWrapping 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 forRunning multiple promises in parallelWrapping callbacks, manual control
ResolutionAutomatically when all promises completeManually with deferred.resolve()
RejectionFails if any promise failsCan reject dynamically
Example Use CaseFetching multiple APIs togetherHandling authentication, external events

Leave a Reply

Your email address will not be published. Required fields are marked *