Wait Till a Function with Animations Is Finished Until Running Another Function

Wait till a Function with animations is finished until running another Function

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/

How do I wait for this animation to finish before moving on to the next one?

To elaborate on entio's answer, your animation occurs when an element has the class "typing-effect." When that animation ends, the browser calls an event called "animationend." You can use JavaScript to run your animation on the next element by accessing that event.

Notice in HTML the snippit below, I've moved the "display: hidden" to a CSS class and removed the "typing-effect." In my JavaScript function, I enable the class in the first element, increment the counter, and told the "animationend" to call the function again with the new value for "i."

Edit: I forgot to mention, I modified the id values. I don't believe a valid id value in HTML5 can contain parenthesis.

console.log("script.js connected");

let iLevel = 1;
let loop = 0;

function animateNext(i){
let stop = document.querySelectorAll('.animated').length;
let animated = document.querySelector(`#h2_${i}`);
animated.classList.add('typing-effect');

animated.addEventListener('animationend', () => {
if(i===stop){
iLevel = "iDone";
}else{
animateNext(i+1);
}
});
}

function startGame() {
animateNext(1);
}
.animated{
display: none;
}
.typing-effect {
display: block;
animation: typing-effect 5s steps(130, end), 0.75s step-end infinite;
white-space: nowrap;
overflow: hidden;
border-right: 2px solid black;
}
.typing-effect:after {
content: " ";
}
@keyframes typing-effect {
0% {
width: 0%;
}
100% {
width: 100%;
}
}
@keyframes blink-caret {
from,
to {
border-color: transparent;
}
50% {
border-color: black;
}
}
<button onclick="startGame();">START GAME</button>

<div id="instructions">

<div>
<h2 id="h2_1" class="animated">Welcome to The Number Wizrd</h2>
</div>

<div>
<h2 id="h2_2" class="animated">Adjfosdf</h2>
</div>
<div>
<h2 id="h2_3" class="animated">sosidjfs</h2>
</div>
<div>
<h2 id="h2_4" class="animated">difjspodf</h2>
</div>
<div>
<h2 id="h2_5" class="animated">skidjfosidf</h2>
</div>

</div>

How to wait until an animation is completed before re-calling a function

You should use the function callback offered by jQuery's .animate() http://api.jquery.com/animate/

var run_program = function() {
$( ".reader" ).animate({
left: "+=50"
}, 600, function() {
// Do something after the Animation is complete.
});
}

Another method would be to get rid of the for loop all together, and in your recursive call just increment the index.

var run_program = function(var index) {
if(typeof index === "undefined") {
//this means it is the first time the function is being run (ie run_program())
index = 0;
}

if (index < program.length) {
//haven't reached the bounds of the initial for loop
//run your other function checks

$('.reader').animate({
left: "+=50"
}, 600, function() {
run_program(index+1);
});
}
}

Can a for-loop wait until a function within it has finished executing?

You can convert your for loop into a recursive function that plays the current button and then tries to play the next button after all animations are done. Something like:

var newRound = function() {
// adds a new round to the end of the game array
game.push(squares[Math.floor(Math.random() * squares.length)]);

// start playing from the first button
playButton(game, 0);
}

function playButton(game, index) {
if (index < game.length) { // if this button exists, play it
var color = game[index];
$("#" + color).addClass(color + "--active active", 300, function() {
$("#audio-" + color).trigger('play');
$("#" + color).removeClass(color + "--active active", 300, function() {
playButton(game, index + 1); // once this button was played, try to play the next button
});
});
}
}

javascript function wait until another function to finish

In my opinion, deferreds/promises (as you have mentionned) is the way to go, rather than using timeouts.

Here is an example I have just written to demonstrate how you could do it using deferreds/promises.

Take some time to play around with deferreds. Once you really understand them, it becomes very easy to perform asynchronous tasks.

Hope this helps!

$(function(){
function1().done(function(){
// function1 is done, we can now call function2
console.log('function1 is done!');

function2().done(function(){
//function2 is done
console.log('function2 is done!');
});
});
});

function function1(){
var dfrd1 = $.Deferred();
var dfrd2= $.Deferred();

setTimeout(function(){
// doing async stuff
console.log('task 1 in function1 is done!');
dfrd1.resolve();
}, 1000);

setTimeout(function(){
// doing more async stuff
console.log('task 2 in function1 is done!');
dfrd2.resolve();
}, 750);

return $.when(dfrd1, dfrd2).done(function(){
console.log('both tasks in function1 are done');
// Both asyncs tasks are done
}).promise();
}

function function2(){
var dfrd1 = $.Deferred();
setTimeout(function(){
// doing async stuff
console.log('task 1 in function2 is done!');
dfrd1.resolve();
}, 2000);
return dfrd1.promise();
}

JQuery wait for any function to finish before starting another- ajax, animations and Audio

Most Ajax operations return a promise, so you can return those:

function ajax_load_file(file){
return $.ajax(...);
}

Animations provide a promise on their queue, so

function play_success_animation()
{
$("#success_div").delay(1000).show(1000);
$("#success_div").delay(500).hide(500);
$("#success_div").fadeOut('slow', function() {
//something else

});
return $("#success_div").promise();
}

Audio provide an end event, but you need to connect/disconnect as required, so use on and off:

function play_transition_audio(path, type){
var def = $.Deferred();
play_audio(path,type);
$("#audio_player").off("ended").on("ended", function(){
def.resolve(path);
});
return def.promise();
}

Then chain either sequentially with then or done (then allows for success and fail callbacks, done only provide success), or in parallel with when:

e.g. Sequential:

   ajax_load_file(file_1).done(play_success_animation)
.then(function(){
return play_transition_audio("audio_path1", "general");
});

You can either specify the function name, if it takes no params and returns a promise, or use an anonymous function in done/then.

e.g. Parallel:

   $.when(ajax_load_file(file_1), play_success_animation(), play_transition_audio("audio_path1", "general"));

Can we make set Interval to wait until its function inside it is executed?

You can use recursion and promises to do this. First wrap the code that you plan to execute in a function that returns a promise. Then create a recursive function that calls itself once the action is complete.

const action = () => new Promise((resolve, reject) => {
console.log("Action init")
return setTimeout(()=>{
console.log("Action completed")
resolve();
},3000)
})

const actionRecursion = () => {
action().then(() => {
setTimeout(actionRecursion, 1000)
})
}

actionRecursion();

How to get jQuery to wait until an effect is finished?

You can specify a callback function:

$(selector).fadeOut('slow', function() {
// will be called when the element finishes fading out
// if selector matches multiple elements it will be called once for each
});

Documentation here.



Related Topics



Leave a reply



Submit