If function_1 contains $.each() functions and an on("load") function, how to make function_2 run afterwards?

74 Views Asked by At

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);
1

There are 1 best solutions below

0
On BEST ANSWER

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);