Processing Multiple AJAX Requests Simultaneously

JavaScriptAJAXWeb Development

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.

Continue Reading

Browse All Articles