0

I want learn about jQuery AJAX using callbacks. So I create this as example.

<?php 
  sleep($_POST['sleep']);
  echo 'sleep for '.$_POST['sleep'] .'sec';
?>
$(function () {
  var timer = [5,2,3,1,4];

  function sleep(timer) {
    $.ajax({
      url: 'ajax.php',
      data: { sleep: timer },
      type: 'post',
      success: function(d){
        console.log(d);
      },
      error: function(d){
        console.log(d);
      }
    });
  } 

  $('#ajax').click(function(){
    $.each(timer, function(i, e) {
      sleep(e);
    })
  });
});

Result: 1,2,3,4,5 What I want is : 5,2,3,1,4 (synchronous)

I know I can using async: false; but this will hang up my browser and this is deprecated too. So I want to learn to doing sync using callback

Here is my fail script:

<script src="http://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script>
<script lang="javascript" type="text/javascript">
$(function () {
  var timer = [5,2,3,1,4];

  $.each(timer, function(i, e) {
    sleep(e, function(d) {
      console.log(d);
    });
  });

  function sleep(sleepTimer, callback) {
    $.ajax({
      url: 'ajax.php',
      data: { sleep: sleepTimer },
      type: 'post',
      success: callback,
      error: function(data){
        console.log(data);
      }
    });
  } 
});
</script>

Result: 1,2,3,4,5 instead 5,2,3,1,4

What am I doing wrong?

UPDATE: Thanks to people who remind me how bad is this. But i dont have any choice right now. My friends need my help to edit his drupal page. He only have admin previledge (not sysadmin). i only can edit view but cannot edit the controllers. why?

  1. only headquarters IT staff who allowed to do that.
  2. need bureaucracy and administration (user requirement, meeting, Quality Assurance [security testing + stress test). and the funny thing is, they check all the apps, not just the page which will affected by my script change only
  3. need time. 1 month is the fastest for non security change

hei.. this sounds funny right? even you just add 1 space, we need number 2 requirement that was they (headquarters staff) said. this true story. i know this because i'm in the same ministry with him.

the script is just download single file by click (of hundred), my friend wants me to add checkbox to allow his team to batch download. i can add checkbox, and download them by sequence (this is what i trying to do with synchronous ajax). but since this will hang up their browser, so i need the right way to doing this.

i have 2 choice here: using phantomjs (medium) or synchronous ajax (easy)

  • 1st reason: since he will not pay me, ofc i choose the easy path.
  • 2nd reason: i always avoid to use sync ajax as possible, but now i want to know how to doing sync ajax using callbacks.
14
  • 4
    I understand that you want to learn, but to be clear - synchronous AJAX is a bad practice which should be avoided in all cases unless there is absolutely no alternative Commented Nov 29, 2017 at 14:53
  • 1
    I can't imagine that there is a single defensible scenario for synchronous Ajax requests in the browser. Commented Nov 29, 2017 at 15:03
  • As an aside - your title is completely misleading: The success callback works properly. What you want to know is how to make AJAX calls in sequence. Commented Nov 29, 2017 at 15:08
  • 1
    @Tomalak the only one I've encountered is when making an AJAX request in onbeforeunload Commented Nov 29, 2017 at 15:09
  • 1
    There are ways to deal with this. Some Promise libraries implement configurable concurrency, Bluebird is one of them. But it would also be possible to implement that yourself. If you can download 10 files in parallel and you have hundreds of files to download, it's a huge waste of time to download all files sequentially. Commented Nov 29, 2017 at 16:18

1 Answer 1

1

TL;DR: Because it's asynchronous not synchronous

The behaviour you are seeing is completely correct for normal asynchronous calls, the order of results is not guaranteed and could be in any order. This is the best way to fire off several AJAX requests, assuming there is no dependency between calls.

For some reason you want to do this synchronously though.

You'll need to change your code so that you only send one request at a time, waiting for the first request to complete before sending the second, etc.

You can achieve this by recursively calling sleep, removing (and using) the first value from timers.

$(function () {
    var timer = [5,2,3,1,4];

    function sleep(timers){

        // check that timers is not empty first.
        if (timers == null || timers.length == 0)
            // if it is, we're done
            return;


        // remove the first value from timers
        var timer = timers.shift();

        $.ajax({
            url: 'ajax.php',
            data: {
                sleep: time
            },
            type: 'post',
            complete: function (jqXHR, textStatus) {
                // complete will get called on either success or error
                console.log(jqXHR);
                //recursively call sleep, first time through timers will be [2,3,1,4]
                sleep(timers);
            }
        });
    }

    $('#ajax').click(function(){
        // send the array of values to sleep instead
        sleep(timer);
    });
});
Sign up to request clarification or add additional context in comments.

4 Comments

This is how sequential calls would be done in jQuery Ajax. stackoverflow.com/questions/24931115/…
If OP is "learning", then it's worth mentioning the notion of callback hell, and a better pattern probably includes using promises or observables.
this answer sounds goods, @cale_b : thanks for your info. i just thinking about using promise now. ill try to find which is the best way
i choose sequential ajax right now. easy and suits for my case. thanks all

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.