Question

I've spent the day reading about deferred, done, promise and callbacks as they seemed relevant to my problem, as well as the many posts on 'how do i run function_2 after function_1' etc.

So I understand the concept that when things happen asynchronously, you need to handle them specifically with one of the above approaches.

In my scenario, function_1 contains $.each() loops and an on.("load"...) function.

I want to run function_2 when function_1 has finished.

If I simply call:

function_1();
function_2();

They don't run sequentially and I am guessing because either $.each or on.("load"...) works asynchronously.

If I try to call function_2 with:

function_1.done(function_2());

I get:

TypeError: function_1.done is not a function.

This leads me to think (and I could be completely off track by this point), that function_1 does not have that method available.

So my questions, possibly based on incorrect assumptions, are:

  • What type of object is returned from function_1 (if it contains $.each() and on.("load"...) functions?
  • Can I enforce that function_1 does have the done() method available?

jsFiddle

As well as the above approach using done(), I tried using a callback which didn't work, although perhaps my method of replicating something that takes time was not correct:

http://jsfiddle.net/rwone/xFX8a/2/

// function 1
function function_1(callback) {
// replicating something that takes a while
// alert("1");
setTimeout(function() {
$("p").append("This should happen first.");
}, 300);
callback();
}

//function 2
// only do this when function one has finished
function function_2() {
alert("This should happen second.");   
};

// the call
function_1(function_2);
Was it helpful?

Solution

Your callback solution would work perfectly, except you're calling the callback in the wrong place:

// function 1
function function_1(callback) {
    // replicating something that takes a while
    // alert("1");
    setTimeout(function() {
        $("p").append("This should happen first.");
        callback(); // <=== Here, when the thing is done
    }, 300);
    // callback();  // <=== Not here, when you've only started it and it's not done yet
}

If you want to use promises instead of an explicit callback, you can do that too. Promises are not part of the JavaScript language; JavaScript functions do not make promises available by themselves, which is why function_1.done didn't work. You create the promise (with jQuery, in the form of a Deferred object) and return it from the function, then use it with the other function:

// function 1
function function_1() {
    var d = new $.Deferred();

    setTimeout(function() {
        $("p").append("This should happen first.");
        d.resolve();    // <=== Resolve the deferred, now that the action is complete
    }, 300);
    return d.promise(); // <=== Return the Promise for the Deferred
}

//function 2
// only do this when function one has finished
function function_2() {
    alert("This should happen second.");   
};

// the call
function_1().done(function_2);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top