Explain Codes LogoExplain Codes Logo

Wait until all jQuery Ajax requests are done?

javascript
async-await
callbacks
promises
Alex KataevbyAlex Kataev·Dec 24, 2024
TLDR

You can use $.when() alongside your $.ajax() requests wrapped inside Array.prototype.map() to handle multiple concurrent Ajax requests. The .then() callback executes once all requests resolved successfully.

var ajaxCalls = [/* array of your Ajax goodies */]; $.when(...ajaxCalls.map(settings => $.ajax(settings))) .then(function() { // Cheers! Your success code here. Arguments contain the juicy results. });

Pay attention to the spread operator ... which helps to pass the array of Deferreds returned by .map() to $.when(). This is a neat way to synchronize multiple Ajax calls.

Following the Dynamic Ajax

When you don't know how many Ajax requests will happen, use a dynamic array of Deferreds:

function performAjaxCalls(callSettingsArray) { var deferreds = callSettingsArray.map(settings => $.ajax(settings)); // Making a dynamic Deferred sandwich 🥪 with ajax and when return $.when(...deferreds); } performAjaxCalls(dynamicSettingsArray).then(function() { // All Ajax calls made it to the finish line });

Remember, using global variables for synchronization can be a bad idea. Instead, wrap your logic within functions and manage scopes effectively.

Riding the success and failure waves

You can use .then() or .fail() to ensure successful as well as failure scenarios are treated with the respect they deserve.

performAjaxCalls(dynamicSettingsArray).then(function() { console.log("All codes worked like a charm!"); }).fail(function() { console.log("Oops! Someone messed up."); });

By splitting your success and error handling, you're making your Ajax call management robust and fail-safe.

Kick it up a notch with async/await

For more readable and less painful coding, async/await syntax can be leveraged with newer jQuery versions:

async function performAjaxCalls(ajaxSettingsArray) { try { await Promise.all(ajaxSettingsArray.map(settings => $.ajax(settings))); console.log("All Ajax calls were a success. Drinks on me 🍻"); } catch (error) { console.error("An Ajax call failed, who dropped the ball?", error); } }

This method lets you write concise error handling code without needing to spell out the .then() or .fail() callbacks.

Organising with ajaxQueue

To maintain an organised workflow, implement a jQuery ajaxQueue, or use .queue() and .dequeue(). These can help with managing requests while ensuring a smooth sailing order of execution and effective callback handling during UI updates.

Semaphore tricks in the bag

For a deeper control over concurrent calls, consider giving a counting semaphore a swing. Here's one way to implement it:

var semaphore = 0; function customAjaxCall(url, semaphoreOperation) { $.ajax({ url: url, success: function(response) { // Woohoo, got a response semaphoreOperation(); }, error: function() { // Bummer! No response semaphoreOperation(); } }); } function semaphoreUp() { semaphore++; } // Points for trying function semaphoreDown() { semaphore--; } // Bummer, take one down // Usage customAjaxCall("api/endpoint1", semaphoreUp); // One call up customAjaxCall("api/endpoint2", semaphoreUp); // Two calls up // ...waiting for all calls if(semaphore === 0) { // All calls made it, everyone's a winner! }

Modify your semaphore logic to better suit your needs. Such an approach can help prevent your beloved code from locking up when you least want it to.