Home » Jquery » javascript – Do something after all asynchronous, nested, $.each database calls are completed

javascript – Do something after all asynchronous, nested, $.each database calls are completed

Posted by: admin February 22, 2020 Leave a comment

Questions:

I’m trying to run a function after 1) all loops are completed and 2) all database calls within those loops are completed.

My database call functions (segmentDatabaseCall and stepDatabaseCall) all take some arguments, resolve a Promise and send the data once the call is complete. This is a (very) simplified version of my code:

let localData = {}

segmentDatabaseCall(argument) // Call the database
.then(segmentResult => { // Returns trip segments (array of objects)

  $.each(segmentResult, (segmentIndex, segmentValue) => { // For each trip segment...

    localData['something'] = segmentValue.something // Add some data to local data

    stepDatabaseCall(segmentValue.segment_id) // Call the database once per trip segment...
    .then(stepResult => { // Returns trip steps (array of objects)

      $.each(stepResult, (stepIndex, stepValue) => { // For each trip step...

        localData['something'][i]['something_else'] = stepValue.something_else // Add some data to local data

        // THIS DOESN'T WORK
        const segsDone = segmentIndex >= segmentResult.length - 1;
        const stepsDone = stepIndex >= stepResult.length - 1;
        if (segsDone && stepsDone) {
          // This if statement runs before all calls are finished 1 out of 3 times roughly
        }
      })
    })
  })
})

Database call:

function databaseCall (argument) {
    return new Promise((resolve, reject) => {
        $.ajax({
          url: $phpUrl,
          type: 'post',
            data: {
              'argument': argument      
            }
        })
        .done (function (data) {
            var resultJson = JSON.parse(data)
            resolve(resultJson)
        })
        .fail (function (error) {
            reject(error)
        })
    })
}

I’ve tried using the answer here, but it runs before all calls are finished 1 in 3 times. I must be missing some counter there?

I also think there’s a way to do this using Promise maps, but I can’t get my head around it.

How to&Answer:

There something called forkJoin in Rxjs. As I understand your question you can use that for your implementation.

forkJoin(
      this._myService.makeRequest('Request One', 2000),
      this._myService.makeRequest('Request Two', 1000),
      this._myService.makeRequest('Request Three', 3000)
    )
    .subscribe(([res1, res2, res3]) => {
      this.propOne = res1;
      this.propTwo = res2;
      this.propThree = res3;
    });

read more from here.

Answer:

Seeing that you are already using JQuery, you can wrap all of your asynchronous calls with the $.when function.

This will allow you to chain together all your promises and manage the completion of all promises with a single .done() function.

https://api.jquery.com/jQuery.when/

From the JQuery website:

$.when( $.ajax( "/page1.php" ), $.ajax( "/page2.php" ) ).done(function( a1, a2 ) {
  // a1 and a2 are arguments resolved for the page1 and page2 ajax requests, respectively.
  // Each argument is an array with the following structure: [ data, statusText, jqXHR ]
  var data = a1[ 0 ] + a2[ 0 ]; // a1[ 0 ] = "Whip", a2[ 0 ] = " It"
  if ( /Whip It/.test( data ) ) {
    alert( "We got what we came for!" );
  }
});