Wednesday, April 9, 2014

Wait Until Loop of jQuery AJAX Requests are Done

I have an application that requires a set of search results to be flagged if the user selects a checkbox in front of the each search result item. I use an each() loop to set the flag of each search result item via an AJAX call. Then there is another requirement to show all flagged items in a different panel. So I wanted to run a function after above jQuery .each() is done. That is after finishing all the Ajax requests in the each() loop.


jQuery.when() can be used in this kind of scenario. It takes a variable number of arguments and makes it possible to call a callback when every argument passed to it is resolved. If the number of Ajax calls are fixed, the syntax will be:

$.when(ajax1(), ajax2(), ajax3(), ajax4()).done(function(a1, a2, a3, a4){
   // code to be executed after four ajax requests complete.
});

But in my case, since the number of selection is not the same always, approach to be used is bit different. Actually I have to pass an array of arguments (deferred objects). So we can use .apply, which makes it possible to call a function with an array of arguments.  

For that I declared an array for deferred objects. Then pass it to the function where each Ajax call is happening.

// Declare an array of Deferred objects.
var searchRsltDeferreds = [];
$('#searchResultsDiv input').each(function () {
  if ($(this).is(':checked')) {
    // Follow selected documents.
    followDocument($(this).val(), searchRsltDeferreds);
  }
  else {
    // Stop following not selected documents.
    stopFollowDocument($(this).val(), searchRsltDeferreds);
  }
});

Then in the followDocument() function (where Ajax call is), I push the request object to the deferred objects array.

// Make the current user start following a document.
var followDocument = function (documentUrl, deferredsArray) {
  var followRequest = $.ajax({
    url: _spPageContextInfo.siteAbsoluteUrl + "/_api/social.following/follow",
    type: "POST",
    data: JSON.stringify({
    "actor": {
      "__metadata": {
        "type": "SP.Social.SocialActorInfo"
      },
      "ActorType": 1,
      "ContentUri": documentUrl,
      "Id": null
      }
    }),
    headers: {
    "accept": "application/json;odata=verbose",
    "content-type": "application/json;odata=verbose",
    "X-RequestDigest": $("#__REQUESTDIGEST").val()
    },
    success: function (responseData) {
      //          
    },
    error: followRequestFailed
  });
  deferredsArray.push(followRequest);
};

When all the objects in the deferred array are resolved, call getMyFollowedDocuments() function which will refresh all flagged items tab.

$.when.apply(null, searchRsltDeferreds).done(function () {
  // Refresh my flagged items tab.
  getMyFollowedDocuments();
});

No comments: