Making parallel API calls with $q.all()

Loading

In AngularJS, when you need to make multiple API calls concurrently and wait for all of them to finish before proceeding, you can use $q.all(). This is particularly useful when you have several independent requests that don’t depend on each other but need to be completed before moving forward with some operation.

1. What is $q.all()?

$q.all() is a method provided by AngularJS’s $q service that allows you to execute multiple promises in parallel and wait for all of them to resolve or reject. It returns a new promise that resolves when all of the input promises are resolved, or it rejects as soon as one of the input promises is rejected.

The $q.all() method is great when you need to perform multiple asynchronous operations (like HTTP requests) in parallel and proceed once all of them are completed successfully.

2. Basic Syntax of $q.all()

$q.all([promise1, promise2, promise3])
.then(function(results) {
// Handle success when all promises are resolved
})
.catch(function(error) {
// Handle failure if any promise is rejected
});

Here, promise1, promise2, and promise3 are the promises you want to resolve in parallel. The results in the .then() function will be an array where each index corresponds to the result of the respective promise in the same order.

3. Example: Making Parallel API Calls

Suppose you need to make three API calls concurrently, and once all of them finish, you want to process their data.

Example:

angular.module('myApp', [])
.controller('MainController', function($scope, $http, $q) {

// API endpoints
var url1 = '/api/data1';
var url2 = '/api/data2';
var url3 = '/api/data3';

// Making API calls
var promise1 = $http.get(url1);
var promise2 = $http.get(url2);
var promise3 = $http.get(url3);

// Using $q.all to execute all promises in parallel
$q.all([promise1, promise2, promise3])
.then(function(results) {
// All promises resolved successfully
$scope.data1 = results[0].data;
$scope.data2 = results[1].data;
$scope.data3 = results[2].data;

console.log('All API responses received:', results);
})
.catch(function(error) {
// One of the promises was rejected
console.error('Error occurred:', error);
$scope.errorMessage = 'An error occurred while fetching data.';
});
});

Explanation:

  1. Promises Creation:
    • $http.get(url1), $http.get(url2), and $http.get(url3) create promises that represent HTTP GET requests to fetch data from three different endpoints.
  2. Using $q.all():
    • $q.all([promise1, promise2, promise3]) executes all three promises in parallel.
    • The .then() method is called once all the promises resolve successfully, and the result of each request is available in the results array. Each element of this array corresponds to the respective promise’s response, which you can then access and use (results[0].data, results[1].data, results[2].data).
  3. Handling Rejection:
    • If any of the promises reject, the .catch() method will be triggered, and the error will be logged or displayed to the user.

4. Handling Error in Parallel API Calls

When using $q.all(), if any one of the promises is rejected, the entire $q.all() promise will be rejected, and none of the other promises’ results will be processed. This is useful when you want to fail fast if any request doesn’t succeed.

Example: Handling Errors

angular.module('myApp', [])
.controller('MainController', function($scope, $http, $q) {

var url1 = '/api/data1';
var url2 = '/api/data2';
var url3 = '/api/data3';

// Make HTTP calls
var promise1 = $http.get(url1);
var promise2 = $http.get(url2);
var promise3 = $http.get(url3);

// Handle parallel requests with $q.all
$q.all([promise1, promise2, promise3])
.then(function(results) {
// All requests were successful
$scope.data1 = results[0].data;
$scope.data2 = results[1].data;
$scope.data3 = results[2].data;
})
.catch(function(error) {
// Handle rejection if any of the requests failed
console.error('An error occurred:', error);
$scope.errorMessage = 'One of the requests failed!';
});
});

In this case, if any of the requests fail, the error message will be shown, and you will know that one or more of the API calls didn’t succeed.

5. Working with Optional or Independent Promises

If you have API calls that are optional or independent (i.e., one doesn’t depend on the other), you can also handle them individually while still using $q.all(). Even if one of the calls fails, you can continue with the rest.

Example: Handling Optional Promises

angular.module('myApp', [])
.controller('MainController', function($scope, $http, $q) {

var url1 = '/api/data1';
var url2 = '/api/data2'; // Optional, might fail
var url3 = '/api/data3';

// Make the HTTP calls
var promise1 = $http.get(url1);
var promise2 = $http.get(url2); // This might fail
var promise3 = $http.get(url3);

// Use $q.all to wait for all promises
$q.all([promise1, promise2, promise3])
.then(function(results) {
// All API calls completed successfully
$scope.data1 = results[0].data;
$scope.data2 = results[1] ? results[1].data : null; // Optional handling for failed request
$scope.data3 = results[2].data;
})
.catch(function(error) {
// If any promise fails, handle the error
console.error('Error occurred in one of the requests:', error);
$scope.errorMessage = 'Some requests failed.';
});
});

In this example, if promise2 fails, it won’t stop the other two promises from being processed, but you’ll handle the failure gracefully by checking if the result is available.

6. When to Use $q.all()

  • Multiple independent requests: When you need to make multiple HTTP requests simultaneously and proceed once all of them are complete.
  • Concurrent requests: Useful when multiple requests are unrelated, and you want to ensure that they are completed in parallel for efficiency.
  • Fail-fast behavior: You want to stop execution as soon as any request fails.

Leave a Reply

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