0

I have code like this. Loop length is grater than 100.

$('.check_box_ping:checked').each(function(i, obj) {
    $.post(
        "mass_ping.php",
        "ping", 
        function(response) {
        }
    );
});

Now 100 $.post() calls occur simultaneously. I want to execute each $.post() sequentially after getting the response of the previous $.post() from the server.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
open source guy
  • 2,727
  • 8
  • 38
  • 61

3 Answers3

6

With a deferred object you could chain all your ajax calls returning a promise inside some chained pipe() methods (see the console output below)

Markup and js

<body>
    <input type="checkbox" checked />
    <input type="checkbox" checked />
    <input type="checkbox" checked />
    <input type="checkbox" checked />  
</body>

<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script>
function doRequest() {
    return $.post("script.php").done(function(response) {
       console.log('Loaded in %d seconds', response);
    });
}

$(document).ready(function(){

    var dfd   = $.Deferred(),
        chain = dfd;

    $('input:checked').each(function() {
        chain = chain.pipe(function() {
            return doRequest().promise();
        });
    });

    chain.done(function() { 
       console.log('done')
    });

    return dfd.resolve();
});
</script>

script.php

<?php
   $seconds = rand(2, 5); 
   sleep($seconds);
   header("Content-type: text/html");
   echo($seconds);
?>

Sleep() was used only to emulate a random latency on the response. On the javascript console you should see something like this:

output

Fabrizio Calderan
  • 120,726
  • 26
  • 164
  • 177
2

The only way to pause your loop for each one is to make the post synchronous which is generally a very bad user experience (it hangs the browser).

What I would suggest instead is that you restructure your loop so you do the next iteration from the completion of the previous post:

(function() {

    var checked = $('.check_box_ping:checked');
    var index = 0;

    function next() {
        if (index < checked.length ) {
            var item = checked.eq(index++);
            // use item here for your post
            $.post({...}, function(response) {
                // do your normal handling of the response here
                ...
                // now kick off the next iteration of the loop
                next();
            });
        }
    }
    next();

})();
jfriend00
  • 683,504
  • 96
  • 985
  • 979
1

You can do 2 things

  1. Change your code so you call the next post from the return function of your first post. This will need some change in your current loop, but would keep everything running smoothly
  2. quicker, but dirty, is to make the post synchronous. You can find out how in this question: how to make a jquery "$.post" request synchronous . I would advice against this, as it would cripple your page during the load(s).
Community
  • 1
  • 1
Nanne
  • 64,065
  • 16
  • 119
  • 163
  • I would advise doing nothing of the above. He should send all the data in one request. – gdoron Jan 09 '13 at 12:59
  • each request trigger 10 curl in server. so take 30s. if i send 100 data at atime it take 100*30s. that will hang my server – open source guy Jan 09 '13 at 13:01
  • To be clear: I agree with @gdoron : it sounds like your way of doing things is structurally wrong, so it might be better to make it not need these hacks. – Nanne Jan 09 '13 at 13:16