2

I have 3 different jQuery functions like:

function step1() {
  ...
}

function step2() {
  ...
}

function step3() {
  ...
}

and if I call them like this:

step1();
step2();
step3();

they will be all executed in the same time. How can I call them one by one so step2(); is called after step1(); is finished and step3(); is called after step2(); is finished.

// MORE INFO

Step1() is executing a json and appends details to html, Step2() is executing another json and appends info in the divs created by Step1() and Step3() simply hides a loading animation.

// THE FUNCTIONS

As requested by some users, here are the functions:

jQuery.noConflict();

jQuery(document).ready(function($) {

    var cardType = $.cookie('cardType');
    var categoryID = $.cookie('categoryID');

    function step1() {
        $.getJSON('http://domain.com/benefits/active/all.json', function(data) {
            $.each(data, function(i,item){
                if (item.benefit_type_id == categoryID) {
                    content = '<li><a class="showDetails" data-offer-description="' + item.description + '" data-offer-period="' + item.begin_date + ' - ' + item.end_date + '"><div class="company" title="' + item.business_id + '"></div><div class="shortdescription">' + item.name + '</div></a></li>';
                    $(content).appendTo("#thelist");
                }
            }); 
            step2();
        });
    } // function step1();

    function step2() {  
        $('.company').each(function(i, item) {
            var tempTitle = item.title;
            $.getJSON('http://domain.com/businesses/from_list/' + tempTitle + '.json', function(data2) {
                $.each(data2, function(i,item){
                    content = '<span>' + item.name + '</span>';
                    $(content).appendTo("div[title='" + tempTitle + "']");
                }); 
                step3();
            });
        });
    } // function step2();

    function step3() {
        loaded();
        $('#loading').delay(1000).fadeOut('slow', function() {
            // Animation complete.
        });
    } // function step3();

    step1();

});
Jeff
  • 12,555
  • 5
  • 33
  • 60
Andrei RRR
  • 3,068
  • 16
  • 44
  • 75
  • 1
    They will be executed sequentially since JavaScript is single-threaded. Or, at least what people commonly make use of. Can you tell us more about what is being run in those functions? – Alexander Jan 21 '13 at 00:00
  • Step1() is executing a json and appends details to html, Step2() is executing another json and appends info in the divs created by Step1() and Step3() simply hides a loading animation. – Andrei RRR Jan 21 '13 at 00:06
  • 1
    JSON cannot be *executed*, it's a *data format*. Do you mean that you are making Ajax requests? – Felix Kling Jan 21 '13 at 00:09
  • Yes, I am making ajax requests. I will update my question and post the exact functions. – Andrei RRR Jan 21 '13 at 00:15
  • possible duplicate of [How to chain ajax requests?](http://stackoverflow.com/questions/995529/how-to-chain-ajax-requests) – Felix Kling Jan 21 '13 at 00:16
  • I've added the exact functions so everybody can see what I am trying to do. – Andrei RRR Jan 21 '13 at 00:22

2 Answers2

6

Not knowing what you are executing in each function, I'm assuming none of them executes an asynchronous call themselves, i.e: ajax request and so on.

Should you have additional asynchronous calls occur in each function the below would not apply as is.

One option would be to use call one from the other similar to this:

function step1() {
    //...
    step2();
}

function step2() {
    //...
    step3();
}

function step3() {
    //...
}

or you can use callbacks in the function signature, similar to this:

//pass step2 function as parameter to step1
//pass step3 function as parameter to step2
step1(step2(step3));

function step1(callback) {
    //...
    callback();
}

function step2(callback) {
    //...
    callback();
}

function step3() {
    //...
}

Or using jQuery deferred might work, similar to this:

$.when($.when(step1()).then(step2)).then(step3);

I'm not 100% sure on the deferred solution using .when().

The code above seems to work (DEMO) using when() but as FelixKing mentioned in the comments if you update the methods to return a deferred promise you can do this:

step1().then(step2).then(step3);

DEMO - Using a deferred promise


Each deferred object must be resolved() though for the next method to be executed.
This would also give you some control if you have a scenario for example in which you don't want to execute step3() if step2() fails to do something and calls .reject() for instance.

Have a play around with the deferred objects in the fiddle and have a look at the deferred promise documentation too for more details.

Sample-Code from DEMO:

step1().then(step2).then(step3);

function step1() {
    var $dfStep1 = new $.Deferred();

    console.log("step1");

    $dfStep1.resolve();
    return $dfStep1.promise();
}

function step2() {
    var $dfStep2 = new $.Deferred();

    console.log("step2");

    $dfStep2.resolve();
    return $dfStep2.promise();
}

function step3() {
    var $dfStep3 = new $.Deferred();

    console.log("step3");

    $dfStep3.resolve();
    return $dfStep3.promise();
}
Nope
  • 22,147
  • 7
  • 47
  • 72
  • You don't need `$.when` in this case. `step1().then(step2).then(step3)` should work fine if they all return deferred objects, promises. – Felix Kling Jan 21 '13 at 00:19
  • Tried the 'step1().then(step2).then(step3)' and step3() never gets to get called. Console Error: Uncaught TypeError: Cannot call method 'then' of undefined – Andrei RRR Jan 21 '13 at 00:25
  • @Andrei: As `FelixKing` mentioned, the function have to return a `promise()` for you to be able to link them with `then()`. Otherwise you get that error. – Nope Jan 21 '13 at 00:32
0

If there is no asynchronous behaviour within the functions then they will be called sequentially. You may be seeing output in the console at different times than you expect, I believe consoles in firefox etc buffer output and can in some cases (although not very often) be misleading.

If you do have asynchronous behaviour within these functions then you either need to make it synchronous or put the call to function2 in the callback to function1 and function3 in the callback to function2. This will ensure that function2 is only called once function1 has reached an apropriate state.

Jon Taylor
  • 7,865
  • 5
  • 30
  • 55