Alert before Ajax request in a loop with JQuery

2020-02-13 02:30发布

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());

3条回答
欢心
2楼-- · 2020-02-13 02:34

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>

查看更多
看我几分像从前
3楼-- · 2020-02-13 02:57

That is because you should do the looping inside the Ajax request callback. When you do it this way, the whole code is executed in a synchronic manner, whilst if you were to do so when the Ajax request callback is invoked, the requests and alerts would be executed like you would expect.

Edit: Here is an example: (generic, you can customize it to your needs)

do(3)

function do(i) {
     if (i === 0) return
     $.ajax({...}).then(function() {
        alert(...)
        do(i-1) 
     })
 }
查看更多
再贱就再见
4楼-- · 2020-02-13 03:01

Everytime ajax call fire it first ask for confirmation. If you allow then only ajax call fire and call for next ajax call and ask for confirmation and so on.. Please check below snippet for more understanding.

//call first time
doAjax(1,3)
//Function to call ajax repeatedly
function doAjax(arrCount,maxCount) 
{
    if (confirm("iteration "+arrCount)) {
        $.ajax({
            url: 'myUrl',
            type: "POST",
            data: {
                // data stuff here
            },
            success: function (data) { 
                arrCount++;
                //Next ajax call when current ajax call has been finished.
                if(arrCount<=maxCount){
                    doAjax(arrCount,maxCount);
                }               
            }         
        });
    }
}
查看更多
登录 后发表回答