refresh a page only when all the ajax scripts are executed

Viewed 103

I'm trying to trigger several actions when clicking a button .button I first need to clean each <div> containing a class .classToClean and launch some ajax scripts to update the database. To do that I choose the $(.classToClean).each(function(index){}); structure and then the ajax $.ajax({}) structure. So far my code look like this.

$(".button").on("click", function () {
  ///// each loop /////
  $( ".classToClean" ).each(function( index ) {
    $.ajax({
      //... (clean 1)
      success:function(response){
        $.ajax({
          //... (clean 2)
          success:function(response){
          }
        });
      }
    });
  });
  ///// /each loop /////
});

Once it's clean I want to write the new statement to the database but this time I only need ajax. As a result I got something like this:

$(".button").on("click", function () {
      ///// each loop /////
      $( ".classToClean" ).each(function( index ) {
        $.ajax({
          //... (clean 1)
          success:function(response){
            $.ajax({
              //... (clean 2)
              success:function(response){
              }
            });
          }
        });
      });
      ///// /each loop /////
      $.ajax({
        //... (write 1)
        success:function(response){
          $.ajax({
            //... (write 2)
            success:function(response){
            }
          });
        }
      });
    });

Everything works fine but I would like to refresh when the each() and the ajax are done. Usually I only got one script so I add a success function like this

success:function(response){
  location.href = "...";
},

But because I got a lot of scripts to run it's seems there are no good place to put it. For example, if I put it in the "write 2" success function sometimes it seems the .each() has not finished and so the page refresh before some scripts are executed. Hence my question: Is there a way to refresh only when all the scripts are executed in the .each and the ajax ?

3 Answers

Map those elements to an array of request promises so you can pass the array to Promise.all();

Note that success is not part of promise chain so you need then() instead

Within each of the outer $.ajax.then() return the #2 ajax promise also to keep building the promise chain

Something like:

const cleanRequests = $('.classToClean').map(function (index, element) {
    // return clean 1 to array
    return  $.ajax({ /*clean 1 options*/}).then(function (clean1_response) {
      // return clean2 promise
      return $.ajax({ /*clean 2 options*/ }).then(function (clean2Response) {
        // not sure what you want returned
      });
    });
  }).get();

Promise.all(cleanRequests).then(function (allCleanResults) {
    // all the clean requests are done, do the write stuff
    return $.ajax({/*write 1 options*/}).then(function (write1_response) {
      return $.ajax({ /*write 2 options*/ }).then(function (write2Response) {
        // not sure what you want returned
      });
    });
  })
  .then(function () {
    /// all done, reload page
  })
  .catch(function (err) {
    console.log('Oooops something went wrong');
  });

try use complete instead of success

complete:function(response){

}

and actually, you don't need to refresh and clean if you just need to replace your div with updated database. just use replaceWith() to replace your div or whole page or html() in case only several element you want to replace and not the whole page

example:

$(".button").on("click", function () {
  $.ajax{
  ....
  complete:function(response){
   updatedDiv = "your div html code";
   $(#yourdiv).replaceWith(updatedDiv);
   }
  });
}

Few ways actually. Dirty way. Initialize a count variable and keep a check and if it goes to 0, then refresh.

var c = 0;
var f = None;
$(".button").on("click", function () {
      f = 1;
      ///// each loop /////
      c +=1;
      $( ".classToClean" ).each(function( index ) {
        $.ajax({
          //... (clean 1)
          success:function(response){
            $.ajax({
              //... (clean 2)
              success:function(response){
                 c -=1;
              }
            });
          }
        });
      });
      ///// /each loop /////
      c +=1 ;
      $.ajax({
        //... (write 1)
        success:function(response){
          $.ajax({
            //... (write 2)
            success:function(response){
               c -= 1;
            }
          });
        }
      });
    });
    while (true) {
       if (c == 0 && f != None) {
          break;
          //refresh here
       }
   }  
});

Added even a more dirtier method to avoid this while loop running first and refreshing early. I would prefer the question poster prefers using @charlietfl 's answer or use underscore method shown below

Goodway: Using underscore after https://underscorejs.org/#after

Related