Processing Multiple AJAX Requests Simultaneously
How to manage multiple asynchronous AJAX calls and process their combined results.
Processing Multiple AJAX Requests Simultaneously
Note: This is a restored article from the original A thousand nodes blog (circa 2012).
I had a requirement where I needed to send multiple service calls and process the data from all these calls together. The challenge was that the data returned, even though in the same format, had various lengths. This meant that one request might have more data than another, affecting the duration of each request/response cycle.
I needed to ensure that the requests were sent simultaneously and trigger a callback only when all responses had been received successfully.
The Solution
Here's a pattern to handle multiple AJAX requests and process their results together:
function processMultipleAjaxRequests(urls, callback) {
var responses = [];
var completedRequests = 0;
// Keep track of which URL's response is which
for (var i = 0; i < urls.length; i++) {
// Use closure to preserve the index
(function(index) {
$.ajax({
url: urls[index],
type: 'GET',
dataType: 'json',
success: function(data) {
// Store the response at the correct index
responses[index] = data;
completedRequests++;
// If all requests are done, call the callback
if (completedRequests === urls.length) {
callback(responses);
}
},
error: function(xhr, status, error) {
console.error('Error in request ' + index + ': ' + error);
// Still count this as completed
completedRequests++;
// Store null or error object at this index
responses[index] = null;
// Check if all requests are done
if (completedRequests === urls.length) {
callback(responses);
}
}
});
})(i);
}
}
Usage Example
var serviceUrls = [
'api/service1',
'api/service2',
'api/service3'
];
processMultipleAjaxRequests(serviceUrls, function(results) {
// results is an array containing all responses in the same order as the URLs
console.log('All requests completed!');
// Process combined results
var service1Data = results[0];
var service2Data = results[1];
var service3Data = results[2];
// Do something with the combined data
processCombinedData(service1Data, service2Data, service3Data);
});
Using jQuery's $.when()
If you're using jQuery 1.5+, there's an easier way using the $.when()
method:
var request1 = $.ajax({
url: 'api/service1',
dataType: 'json'
});
var request2 = $.ajax({
url: 'api/service2',
dataType: 'json'
});
var request3 = $.ajax({
url: 'api/service3',
dataType: 'json'
});
$.when(request1, request2, request3).done(function(response1, response2, response3) {
// All requests have completed successfully
// Each response is an array: [data, statusText, jqXHR]
var data1 = response1[0];
var data2 = response2[0];
var data3 = response3[0];
// Process the combined data
processCombinedData(data1, data2, data3);
}).fail(function() {
// One or more requests failed
console.error('One or more requests failed');
});
Modern Approach Using Promises
In modern JavaScript, you can use Promise.all():
// Create an array of fetch promises
const promises = [
fetch('api/service1').then(response => response.json()),
fetch('api/service2').then(response => response.json()),
fetch('api/service3').then(response => response.json())
];
// Wait for all promises to resolve
Promise.all(promises)
.then(results => {
// results is an array of all the resolved values
const [data1, data2, data3] = results;
// Process the combined data
processCombinedData(data1, data2, data3);
})
.catch(error => {
console.error('One or more requests failed:', error);
});
This pattern is extremely useful when you need to combine data from multiple sources before rendering a UI component or performing complex calculations.