JQuery Ajax Wait Every Function

$xy('#simpan').click(function() {

  $xy('input[id="cekbok[]"]:checked').each(function() {

    var data = (this.value);
    var div = (this.value);
    var str = window.location.href;
    var res = str.replace("wp-admin/options-general.php?page=katalogu-options", "/wp-content/plugins/katalog/includes/img/loading.gif");
    var loading = ('<img src="'+res+'">') ;


    $xy.ajax({
        type : 'POST',
        url : '../wp-content/plugins/katalogunique/proses2.php',           
        data: {
            id  : (this.value)
        },

        success:function (data) {
            $xy('#result'+div).empty();
            $xy('#result'+div).append(data);
            $xy('#tz'+div).remove();
        }          

    });  

  });
});

      

My function passes the values ​​of the labels in proses2.php

in a loop, but when I run this script, it fires all the ajax POST calls at once. I want to run 1 on 1 ajax requests or wait until complete, how can I solve this problem?

+2


source to share


3 answers


Here's a way that doesn't have recursion and uses a simple loop:

$xy('#simpan').click(function() {

    var url = '../wp-content/plugins/katalogunique/proses2.php';
    var d = $.Deferred().resolve(); // empty promise
    $xy('input[id="cekbok[]"]:checked').each(function() {
        var div = this.value;
        d = d.then(function(data){
            $xy('#result'+div).empty().append(data);
            $xy('#tz'+div).remove();
            return $xy.post(url, {id: div}); // this will make the next request wait
        });
    });
    // can d.then here for knowing when all of the requests are done.
});

      

Note. I can "fix it" with .reduce

, reducing the number of lines from 6 to 4, but honestly, I would rather keep the OP's loop. This works because of the conversation chain - basically, when you return an action from then

, it will wait for it until the next then

one you bind it to.

Let's consider:



function log(msg){ // simple function to log stuff
    document.body.innerHTML += msg + "<br />";
}

var delay = function(ms){ // this is an async request, simulating your AJAX
   var d = $.Deferred();
   setTimeout(d.resolve, ms); // resolving a deferred makes its then handlers execute
   return d;
};

// $.Deferred.resolve() starts a new chain so handlers execute
var p = $.Deferred().resolve().then(function(){ 
    log("1");
    return delay(1000); // like in your code, we're waiting for it when we chain
}).then(function(){ // in the above code, this is the d = d.then part,
    log("2"); // this only runs when the above delay completes
    return delay(1000);
});

// and more like in the above example, we can chain it with a loop:
[3,4,5,6,7,8,9,10].forEach(function(i){
     p = p.then(function(){
         log(i);
         return delay(1000);
     });
});
      

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      

Run code


Note that doing $xy('#result'+div)

is probably a bad idea since you are asking your presentation layer for something you put there - consider storing the relevant divs as an array and storing the links instead.

+5


source


You can use a recursive function like this to make all the calls one by one:

$xy('#simpan').click(function() {
    var str = window.location.href;
    var i=0; things = $xy('input[id="cekbok[]"]:checked');
    (function doOneTask(){
        if (i++>=things.length) return;
        var thing = things[i];
        var data = thing.value;
        var div = thing.value;
        var res = str.replace("wp-admin/options-general.php?page=katalogu-options", "/wp-content/plugins/katalog/includes/img/loading.gif");
        var loading = ('<img src="'+res+'">') ;
        $xy.ajax({
            type : 'POST',
            url : '../wp-content/plugins/katalogunique/proses2.php',           
            data: {
                id  : thing.value
            },
            success:function (data) {
                $xy('#result'+div).empty();
                $xy('#result'+div).append(data);
                $xy('#tz'+div).remove();
            }          
        }).always(doOneTask);
    })();
});

      



Note : if you want to stop at the first failure, instead of making the next calls like me, replace always

with done

.

+1


source


One way is to use a recursive function, passing in a list (minus the first entry) each time.

eg. the calling code boils down to this:

$xy('#simpan').click(function() {
    LoadAjax($xy('input[id="cekbok[]"]:checked'));

});

      

and LoadAjax recursively looks like this:

function LoadAjax(elements) {
    // Exit when done
    if (!elements.length) return;
    var $this = elements.first();
    var data = ($this.value);
    var div = ($this.value);
    var str = window.location.href;
    var res = str.replace("wp-admin/options-general.php?page=katalogu-options", "/wp-content/plugins/katalog/includes/img/loading.gif");
    var loading = ('<img src="' + res + '">');

    $xy.ajax({
        type: 'POST',
        url: '../wp-content/plugins/katalogunique/proses2.php',
        data: {
            id: ($this.value)
        },

        success: function (data) {
            $xy('#result' + div).empty();
            $xy('#result' + div).append(data);
            $xy('#tz' + div).remove();
            // Go recursive with the rest of the list
            LoadAjax(elements.slice(1));
        }

    });
}

      

0


source







All Articles