KumarV
KumarV

Reputation: 162

Code to run after .each loop is completed

I have tried many different ways to do this.
Like in below code I have tried to run a code after the .each iteration is completed.

  function test(){
    var iterate = $.each(ohrArray, function(i, val){

      var ohrID = ohrArray[i];
      var folderUrl = 'EFMSEmployeeDocumentList' + "/" + locationFolder;
      var url = _spPageContextInfo.webServerRelativeUrl + "/_api/Web/GetFolderByServerRelativeUrl('" + folderUrl + "')?$expand=Files";

      $.getJSON(url,function(data,status,xhr){

        for(var i = 0; i < data.Files.length;i++){
          modifiedDate= new Date(data.Files[i].TimeLastModified);
          if(documentTitle == ""){
            showData(ohrID ,data.Files[i].Title,data.Files[i].ServerRelativeUrl,modifiedDate);
            countItems++;
          }else{
            if(documentTitle == data.Files[i].Title)

              countItems++;
              showData(ohrID ,data.Files[i].Title,data.Files[i].ServerRelativeUrl,modifiedDate);
          }
        }
      }
    }).complete(function(){

      $('#tblCustomListData').dataTable({
        paging: true,
        searching: true,
        bDestroy: true,
        "iDisplayLength": 5,
        "lengthMenu": [5,10, 25, 50, 100]
      });
      if(countItems == 0){
        alert("No Files Exists");
        $("#divCustomListData").hide();
      }
    });
  }
});


  $.when(iterate)
  .then(function(iterate){
    if(countItems == 0){
      alert("No Files Exists");
    }
  });
}

Still while debugging I see that the code of .then is running before the .each has completed.

What else can we do?

Upvotes: 0

Views: 196

Answers (3)

vassiliskrikonis
vassiliskrikonis

Reputation: 596

iterate should be a Promise.

When you pass in $.when() something that's not a Promise it defaults to an already resolved one so the $.then() is executed immediately.

To use Promises in jQuery check $.Deferred

Then again, you're checking countItems which gets updated only when each ajax call responds. So what you really need is to ditch .complete() altogether and have an array of Promises. Each iteration in .each will create a new Promise in the array and then we'll use $.when() to check when all the Promises are resolved.

function test(){
    var promises = []; //

    $.each(ohrArray, function(i, val){
      var d = $.Deferred(); // keep the reference to the promise
      promises.push(d); // push the promise into the array

      var ohrID = ohrArray[i];
      var folderUrl = 'EFMSEmployeeDocumentList' + "/" + locationFolder;
      var url = _spPageContextInfo.webServerRelativeUrl + "/_api/Web/GetFolderByServerRelativeUrl('" + folderUrl + "')?$expand=Files";

      $.getJSON(url,function(data,status,xhr){

        for(var i = 0; i < data.Files.length;i++){
          modifiedDate= new Date(data.Files[i].TimeLastModified);
          if(documentTitle == ""){
            showData(ohrID ,data.Files[i].Title,data.Files[i].ServerRelativeUrl,modifiedDate);
            countItems++;
          }else{
            if(documentTitle == data.Files[i].Title)

              countItems++;
              showData(ohrID ,data.Files[i].Title,data.Files[i].ServerRelativeUrl,modifiedDate);
          }
        } // end of for loop
        d.resolve(); // the ajax in this iteration has been resolved
      }
    });

    // $.when doesn't accept array of promises by default
    $.when.apply(this, promises).then(function(){
      // now all the promises have been resolved

      // code inside the .complete you had in your question
      $('#tblCustomListData').dataTable({
        paging: true,
        searching: true,
        bDestroy: true,
        "iDisplayLength": 5,
        "lengthMenu": [5,10, 25, 50, 100]
      });
      if(countItems == 0){
        alert("No Files Exists");
        $("#divCustomListData").hide();
      }

      iterate.resolve();
    });
  }
});


}

I may have misformatted or misplaced some brackets because i didn't run the code.

Upvotes: 2

UfguFugullu
UfguFugullu

Reputation: 2147

I've found a solution from dataTable here

$(document).ready(function() {
    $('#example').DataTable( {
        "ajax": "data/objects.txt",
        "columns": [
            { "data": "name" },
            { "data": "position" },
            { "data": "office" },
            { "data": "extn" },
            { "data": "start_date" },
            { "data": "salary" }
        ]
    } );
} );

Otherwise I think you should change your API so you can give the API a list of folderURLs.
Then you don't need to send a request in every loop of your .each().
Further you should be able to create the dataTable in the success callback of one and only getJSON

Upvotes: 0

void
void

Reputation: 36703

You are make XMLHTTPRequeat inside the $.each so I suppose you want to execute some code when all the requests are processed. This won't happen directly as JS is async in nature.

You can keep some counter variable to keep track of the total requests processed. Something like this:

var iterate = $.each(ohrArray, function(i, val) {

      var url = "......";
      var counter = 0;
      $.getJSON(url, function(data, status, xhr) {

        counter++;
        /**** Rest of the code ****/

        if (counter == ohrArray.length) {
          // Execute the required code by pasting it here or calling a function.
        }

      });

    }

Upvotes: 0

Related Questions