Youssef Khloufi Youssef Khloufi - 2 months ago 18
Ajax Question

Alert before Ajax request in a loop with JQuery

I am trying to have a loop that asks the user for a confirmation before doing a synchronous ajax request and it is not working in order. This is my code:

<script>
$(document ).ready(function() {
for(var i = 0; i < 3; i++) {
alert("iteration "+i);
$(".demo").easyOverlay("start");
$.ajax({
async: false,
url: "http://rest-service.guides.spring.io/greeting"
}).then(function(data) {
$('.demo').append(data.id);
$('.demo').append(data.content);
$(".demo").easyOverlay("stop");
});
}
});
</script>


The behaviour I am having with my code is like this:


  • Ask for the first confirmation.

  • Ask for the second confirmation.

  • Ask for the third confirmation.

  • Executed the three ajax calls one after the other.



It looks like for some reason all the ajax calls gets delayed until the alerts are all confirmed and I don't know why. I tried to achieve my same goal without using a loop and by repeating the code 3 times and I get the same exact strange behaviour.

Edit:

If i put the following line in 'then()' to check if the html is actually modified I can see in the console that the things actually happens in order and they just don't appears in the browser until I confirm every alert and that's what gives the impression that the order of execution is not correct. So I need to figure out why reflecting the changes done to the html is delayed and is not done immediately.

console.log($('.demo').html());

Answer

IMO jQuery.Deferred() object will be the most promising way.

  • The Deferred object, is a chainable utility object created by calling the jQuery.Deferred() method. It can register multiple callbacks into callback queues, invoke callback queues, and relay the success or failure state of any synchronous or asynchronous function.

  • deferred objects can be used for processing asynchronous events - you initiate an action and then register a callback which will be invoked when the action has completed. This includes AJAX, although there are plenty of other uses too.

Where asks for resolved

function callAjaxMethod(url, step) {
  return $.Deferred(function() {
        //Confirm box for use inputs
        if(confirm(step))
        {
          //Ajax call 
          $.ajax(url).done(function(data){
             //Do something
             //Update your HTML if needed 
          });
        }
        setTimeout(function() {
          //This will resolve your call again
          this.resolve();
        }.bind(this), 1000);
  })
}

Deferred object

var defer = $.Deferred().resolve();
var counters = [1, 2, 3, 4, 5];
$.each(counters, function(key, value) {
    defer = defer.then(function() {
      return callAjaxMethod('URL', value);
    });
});

It will call when all done

defer.then(function() {
  //It will call when all done
});

Few of the documentation

Official jQuery.Deferred

Call ajax via jQuery deferred's

Article on Multiple jQuery promises

Hope this helps you :)

var $demo = $('#demo');
var ajaxURL = 'https://jsonplaceholder.typicode.com/posts';
function callAjaxMethod(url, step) {
  return $.Deferred(function() {
        //Confirm box for user inputs
        if(confirm(step))
        {
          //Ajax call 
          $.ajax(url).done(function(data){
            //Do something
            //console.log(data);
            
            //Update the HTML OK
            $demo.append(step + ": Success" + "<br/>");
          });
        }
        else
        {
          //Update the HTML when cancel
          $demo.append("<font color='red'>"+ step +": Cancelled </font>" + "<br/>");
        } 
        //Use timeout to get the resolved
        setTimeout(function() {
          this.resolve();
        }.bind(this), 1000);

  })
}
//Defer object
var defer = $.Deferred().resolve();
var counters = ['call 1', 'call 2', 'call 3', 'call 4', 'call 5'];
//Loop your calls
$.each(counters, function(key, value) {
    defer = defer.then(function() {
      return callAjaxMethod(ajaxURL, value);
    });
});

defer.then(function() {
  //It will call when all done
  $(demo).append("<br/><br/>"+"ALL DONE");
});
div
{
  color: blue;
  font-size: 14px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="demo"></div>