javascriptjqueryajax

How do I use jQuery promises to chain one ajax call, then a loop of ajax calls, then make use of an accumulated result?


I am struggling mightily to figure out the correct use of $.when, .then or .done, and probably $.each to achieve what I need here. Everything I try fails in one way or another: code runs out of order, a call doesn't get made at all, etc.

I need to create a function that does the following things in this specific order:

  1. Makes an ajax call to retrieve the Name of a table based on its ID (which is the value from a dropdown on the page; the dropdown has already been retrieved with jQuery):
// querying UserEntities(id) returns certain metadata for the user-created table with that ID
$.ajax({
   type: 'GET',
   url: serviceURL + 'UserEntities(' + entity.val() + ')',
   dataType: 'json',
   processData: true,
   success: function (tblData) {
      return tblData.value[0].Name;
   }
})
  1. Using the retrieved table Name from step 1 (tblName in the code below), loops through an array of objects to see if a certain property of that object appears in a certain column of the table, building up an array of the objects that do appear:
$.each(items, function (i, item) {
   $.ajax({
      type: 'GET',
      url: serviceURL + tblName + '?$filter=' + attributeName + ' eq \'' + item.MyPropName+ '\'&$top=0&$count=true',
      dataType: 'json',
      processData: true,
      success: function (data) {
         if (data["@odata.count"] && data["@odata.count"] > 0) {
            itemsInTable.push(item);
         } else {
            // ...do some simple thing on the page...
         }
      }
   });
});
  1. Generates a popup with the list of items that appear in the table:
if (itemsInTable.length > 0) {
   // ...do some stuff...
}

To be clear, I am not asking how to make a popup. This is purely about making sure all the ajax calls get made - and in the proper order - before the code ever gets to part 3 where it's checking the length of the array. Step 1 needs to finish before step 2, and then step 2 needs to finish (every ajax call in the loop has to complete) before step 3.


Solution

  • You can use jQuery's $.when, $.then, and $.each to chain and manage the asynchronous operations properly.

    1. Use $.when to wait for the first AJAX call (retrieving the table name).
    2. Use $.each combined with $.when to ensure each item check completes before moving on to the next.
    3. Use .then or .done to ensure the final part runs only after all AJAX calls in step 2 complete.
    // Step 1: Retrieve the table name based on the entity ID
    $.ajax({
        type: 'GET',
        url: serviceURL + 'UserEntities(' + entity.val() + ')',
        dataType: 'json',
        processData: true
    }).then(function (tblData) {
        var tblName = tblData.value[0].Name;
        var ajaxCalls = [];
    
        // Step 2: Loop through an array of objects and check if they exist in the table
        $.each(items, function (i, item) {
            var ajaxCall = $.ajax({
                type: 'GET',
                url: serviceURL + tblName + '?$filter=' + attributeName + ' eq \'' + item.MyPropName + '\'&$top=0&$count=true',
                dataType: 'json',
                processData: true
            }).then(function (data) {
                if (data["@odata.count"] && data["@odata.count"] > 0) {
                    itemsInTable.push(item);
                } else {
                    // ...do some simple thing on the page...
                }
            });
            ajaxCalls.push(ajaxCall);
        });
        // Step 3: Wait for all AJAX calls in the loop to complete
        return $.when.apply($, ajaxCalls);
    
    }).then(function () {
        // Step 4: Generate a popup if any items are found in the table
        if (itemsInTable.length > 0) {
            // ...do some stuff...
            console.log("Items in table:", itemsInTable);
        }
    }).fail(function (error) {
        console.error("An error occurred: ", error);
    });