I'm having an issue with normal (non-ajax) functions that involve lots of animations within each of them. Currently I simply have a setTimeout
between functions, but this isn't perfect since no browsers / computers are the same.
Additional Note: They both have separate animations/etc that collide.
I can't simply put one in the callback function of another
// multiple dom animations / etc FunctionOne(); // What I -was- doing to wait till running the next function filled // with animations, etc setTimeout(function () { FunctionTwo(); // other dom animations (some triggering on previous ones) }, 1000);
Is there anyway in js/jQuery to have:
// Pseudo-code -do FunctionOne() -when finished :: run -> FunctionTwo()
I know about $.when()
& $.done()
, but those are for AJAX...
jQuery has an exposed variable (that for some reason isn't listed anywhere in the jQuery docs) called $.timers, which holds the array of animations currently taking place.
function animationsTest (callback) { // Test if ANY/ALL page animations are currently active var testAnimationInterval = setInterval(function () { if (! $.timers.length) { // any page animations finished clearInterval(testAnimationInterval); callback(); } }, 25); };
Basic useage:
// run some function with animations etc functionWithAnimations(); animationsTest(function () { // <-- this will run once all the above animations are finished // your callback (things to do after all animations are done) runNextAnimations(); });
You can use jQuery's $.Deferred
var FunctionOne = function () { // create a deferred object var r = $.Deferred(); // do whatever you want (e.g. ajax/animations other asyc tasks) setTimeout(function () { // and call `resolve` on the deferred object, once you're done r.resolve(); }, 2500); // return the deferred object return r; }; // define FunctionTwo as needed var FunctionTwo = function () { console.log('FunctionTwo'); }; // call FunctionOne and use the `done` method // with `FunctionTwo` as it's parameter FunctionOne().done(FunctionTwo);
you could also pack multiple deferreds together:
var FunctionOne = function () { var a = $.Deferred(), b = $.Deferred(); // some fake asyc task setTimeout(function () { console.log('a done'); a.resolve(); }, Math.random() * 4000); // some other fake asyc task setTimeout(function () { console.log('b done'); b.resolve(); }, Math.random() * 4000); return $.Deferred(function (def) { $.when(a, b).done(function () { def.resolve(); }); }); };
http://jsfiddle.net/p22dK/
add the following to the end of the first function
return $.Deferred().resolve();
call both functions like so
functionOne().done(functionTwo);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With