12

I want to use jQuery's load function to load some content into a div, and I want to also call jQuery's animate function.

$('#div1').load('...', function() {
    // load complete
});

$('html,body').animate({
    ...: ...}, ..., '...', function(){
    // animate complete
});

I don't want to wait for load to complete before calling animate or vice versa.

Following this I want to call a third function, but I don't want to call it until the complete event for both the load and the animate have been fired.

How can I do this?

Andy
  • 7,646
  • 8
  • 46
  • 69

5 Answers5

40

Sounds like a job for Deferred: http://api.jquery.com/category/deferred-object/

var load = $.Deferred(function (dfd) {
  $('#div1').load(…, dfd.resolve);
}).promise();

var animate = $('html,body').animate(…);

$.when(load, animate).then(function () {
  // Do your thing here!
});
qerub
  • 1,526
  • 16
  • 11
  • 1
    `.animate(…)` does not return a deffered! (and I think that `.load` doesn't either...) – Joseph Silber Sep 15 '11 at 14:59
  • 2
    Actually, animations work like deferreds: http://bugs.jquery.com/ticket/7934. I'm not sure how `.load` works. – qerub Sep 15 '11 at 15:28
  • 2
    WOW! I didn't know that! What's interesting though, is that the *jQuery collection itself* becomes the deferred: http://jsfiddle.net/jgbUX/ . **Really interesting.** – Joseph Silber Sep 15 '11 at 15:39
  • @joseph-silber: I'm happy that you discovered something new. :) I've checked `.load` and its return value is not a deferred, so I've updated my solution to wrap it manually. – qerub Sep 15 '11 at 15:51
  • Thanks -- one simple example can be worth 1000 words in documentation. Learned too many new concepts. Brain hurting.. – Gerard ONeill Oct 14 '15 at 23:28
5
var _loadComplete = false;
var _animateComplete = false;

$('#div1').load('...', function() {
    // load complete
    _loadComplete = true;
    checkComplete(); 
});

$('html,body').animate({
    ...: ...}, ..., '...', function(){
    // animate complete
    _animateComplete = true;
    checkComplete();
});

function checkComplete() {
    if(_loadComplete && _animateComplete)
        runThirdFunction();
});
BumbleB2na
  • 10,723
  • 6
  • 28
  • 30
3

You'll have to keep count of how many of your events have completed, and then use that as a test in your callback:

var complete = 0;

$('#div1').load('...', function() {
    complete++;
    callback();
});
$('html,body').animate({
    ...: ...}, ..., '...', function(){
    complete++;
    callback();
});

function callback(){
    if ( complete < 2 ) return;
    // both are complete
}
Joseph Silber
  • 214,931
  • 59
  • 362
  • 292
2

Set a flag in LoadComplete and call your own 'allComplete' function. Set another flag in AnimateComplete and call that same 'allComplete' function.

In allComplete you check if both flags are set. If they are, both async functions are complete and you can call your third function.

Instead of setting flags (separate variables), you can also add 1 to a global counter, that way, you can increase the number of async functions to wait for without having to introduce extra flag variables.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
1

Use:

$('#div1').queue(function(){ /* do stuff */ });

This way you can queue functions to execute one after the other.

Andrew Church
  • 1,391
  • 11
  • 13