4

I want to make some wine. And my function does:

function wine(){
    growGrapes();
    process(grapes);
    makeWine();
    bottle();
}

However, Since my functions often consist of $.ajax() request, some other functions get carried out first. I have used the success tool, but it helps for one ajax request only.

success:function(result){
    //Some Code         
}

What I actually want is a sequence. Literally, grapes get processed before growing them. What is a easiest approach?

tika
  • 7,135
  • 3
  • 51
  • 82

6 Answers6

4

jQuery Deferred Objects & Promises are the way to go. http://api.jquery.com/category/deferred-object/

They supports running multiple tasks in parallel or series using $.when(PassArrayOfPromisesToRunInParallel) to run processes in parallel and promise.then() to run items sequentially.

iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
3

Call the next function in the success handler of the $.ajax call of the previous function!

Example:

function growGrapes(){
  // lines of code
  $.ajax({
    success: function(result){
      // call next function here - process(grapes); and so on...
    }   
  });   
}

The above makes sure the functions get called sequentially after the other..

Amit Joki
  • 58,320
  • 7
  • 77
  • 95
1

First solution :

Make your ajax call syncronous by setting async : false when setting up your ajax call

$.ajax
({
   async : false,
   /* other settings */
});

Warning: This solution causes the UI to hand on intensive processing. This should never be used when doing anything rigorous on the server. My recommendation for using this is to only use it in checking flags or loading simple data.

Second solution :

As stated in the comments, use jQuery promises to set up the ordering. Here is a tutorial

I'll try to come back and provide a code example for this solution soon

Third solution :

Make your next call the success handler, or call the next step from the success handler

$.ajax
({
   success : NextStep,
   /* other settings */
})
Brett Weber
  • 1,839
  • 18
  • 22
  • Never *ever* recommend `async: false`. It will cause far more problems than doing it properly. The 2nd and 3rd options are suitable. – iCollect.it Ltd Jul 17 '14 at 14:52
  • I disagree. I use this in simple cases where the processing is trivial, such as checking a flag on the server to see if a user is logged in, and it works beautifully in keeping my logic flow simple by not having to pass a callback function to the method checking the user's state. That being said, I should make a not of that since I do agree it is ashow stopped on more intensive calls – Brett Weber Jul 17 '14 at 14:55
  • And you have no problem in tying up the browser if the response time is lengthy? Feel free to disagree but you will find more people on SO will agree with *never use `async: false`* :) – iCollect.it Ltd Jul 17 '14 at 14:57
  • haha, I just corrected my comment to include that, and I will update my answer. Thank you for being thorough. – Brett Weber Jul 17 '14 at 14:58
  • Well done... but will will have to agree to disagree if you feel there is any reason to ever use `async: false` :) – iCollect.it Ltd Jul 17 '14 at 14:58
  • 3
    The problem is that async: false is unpredictable. There can always be problems with the network connection and if the delay is too big, the unresponsive UI is noticeable which is the worst user experience. Of course if you don't write production code, you can do whatever you want ;) Promises make coding async processes very simple. – Felix Kling Jul 17 '14 at 14:59
  • 1
    @FelixKling - Fantastic point. I haven't run into an issue like that so far using my methods, and it never occurred to me that something like this may happen. I'll have to present it to our product manager to start a discussion on the value in changing over to using deferred objects instead of async false. Assuming he deems the effort worth the outcome I may be inclined to do some research and potentially change my opinion. – Brett Weber Jul 17 '14 at 15:03
1

You can make your Ajax calls synchronous (in sequence) by ensuring you have async: false in your $.ajax() settings.

For example:

$.ajax({ url: 'url', 
         async: false,
         dataType: 'json',
         success: function(data) {

         }
});
benjrb
  • 766
  • 1
  • 5
  • 13
  • 1
    Never *ever* recommend `async: false`!!! It will cause far more problems than doing it properly. That certainly would not help with any parallel requirements. (Who upvoted this?) – iCollect.it Ltd Jul 17 '14 at 14:48
  • Where are the parallel requirements here? – benjrb Jul 17 '14 at 14:50
  • Not explicit, but commonplace, however not the point. `async: false` is a disaster waiting to happen and should be removed from jQuery.ajax completely (IMHO)! – iCollect.it Ltd Jul 17 '14 at 14:51
0

One solution is to use queue() function. This way you can execute as many functions as you want

    var ajaxQueue = $({});


    $.ajaxQueue =  function(ajaxOpts) {  

        // queue the method. a second call wont execute until this dequeues
        ajaxQueue.queue(function(next) {
            // for this example I serialize params, but you can save them in several variables 
            // and concat into ajaxOpts.data
            var params = method_that_get_params_and_serialize_them();
            ajaxOpts.data = params;      

            ajaxOpts.complete = function() {       
                next();
            };

            $.ajax(ajaxOpts);
        });
    };

then your functions should be like this:

    function growGrapes(){
        $.ajaxQueue({
            cache: false,
            type: "POST",
            url: "someUrl",
            dataType: "json",
            data: "", // we fill data inside  ajaxQueue() method
            success: function( response) {                      
                //do things with response

            } 
        });
    }
EduSanCon
  • 1,749
  • 1
  • 11
  • 9
0

If you want to keep it tidy and clean to let people see how your calls are made, you can simply pass a callback function to another like this:

function growGrapes(callback) {
  $.ajax({
  ...
    success: function (){
      // Something
      if (typeof callback === typeof Function) callback();
    },
  ...
  });
} 

function wine(){
  growGrapes(function (){
    process(grapes);
  });
}
Edward
  • 1,914
  • 13
  • 26