function a() { // first function code here $(document). trigger('function_a_complete'); } function b() { // second function code here } $(document). bind('function_a_complete', b); Using this method, function 'b' can only execute AFTER function 'a', as the trigger only exists when function a is finished executing.
In order to run a function multiple times after a fixed amount of time, we are using few functions. setInterval() Method: This method calls a function at specified intervals(in ms). This method will call continuously the function until clearInterval() is run, or the window is closed.
function Typer(callback) { var srcText = 'EXAMPLE '; var i = 0; var result = srcText[i]; var interval = setInterval(function() { if(i == srcText. length - 1) { clearInterval(interval); callback(); return; } i++; result += srcText[i]. replace("\n", "<br />"); $("#message").
JavaScript is synchronous. This means that it will execute your code block by order after hoisting. Before the code executes, var and function declarations are “hoisted” to the top of their scope.
In Javascript, there are synchronous and asynchronous functions.
Most functions in Javascript are synchronous. If you were to call several synchronous functions in a row
doSomething();
doSomethingElse();
doSomethingUsefulThisTime();
they will execute in order. doSomethingElse
will not start until doSomething
has completed. doSomethingUsefulThisTime
, in turn, will not start until doSomethingElse
has completed.
Asynchronous function, however, will not wait for each other. Let us look at the same code sample we had above, this time assuming that the functions are asynchronous
doSomething();
doSomethingElse();
doSomethingUsefulThisTime();
The functions will be initialized in order, but they will all execute roughly at the same time. You can't consistently predict which one will finish first: the one that happens to take the shortest amount of time to execute will finish first.
But sometimes, you want functions that are asynchronous to execute in order, and sometimes you want functions that are synchronous to execute asynchronously. Fortunately, this is possible with callbacks and timeouts, respectively.
Let's assume that we have three asynchronous functions that we want to execute in order, some_3secs_function
, some_5secs_function
, and some_8secs_function
.
Since functions can be passed as arguments in Javascript, you can pass a function as a callback to execute after the function has completed.
If we create the functions like this
function some_3secs_function(value, callback){
//do stuff
callback();
}
then you can call then in order, like this:
some_3secs_function(some_value, function() {
some_5secs_function(other_value, function() {
some_8secs_function(third_value, function() {
//All three functions have completed, in order.
});
});
});
In Javascript, you can tell a function to execute after a certain timeout (in milliseconds). This can, in effect, make synchronous functions behave asynchronously.
If we have three synchronous functions, we can execute them asynchronously using the setTimeout
function.
setTimeout(doSomething, 10);
setTimeout(doSomethingElse, 10);
setTimeout(doSomethingUsefulThisTime, 10);
This is, however, a bit ugly and violates the DRY principle[wikipedia]. We could clean this up a bit by creating a function that accepts an array of functions and a timeout.
function executeAsynchronously(functions, timeout) {
for(var i = 0; i < functions.length; i++) {
setTimeout(functions[i], timeout);
}
}
This can be called like so:
executeAsynchronously(
[doSomething, doSomethingElse, doSomethingUsefulThisTime], 10);
In summary, if you have asynchronous functions that you want to execute syncronously, use callbacks, and if you have synchronous functions that you want to execute asynchronously, use timeouts.
promises
, a JavaScript feature of the ECMAScript 6
standard. If your target platform does not support promises
, polyfill it with PromiseJs.Look at my answer here Wait till a Function with animations is finished until running another Function if you want to use jQuery
animations.
Here is what your code would look like with ES6 Promises
and jQuery animations
.
Promise.resolve($('#art1').animate({ 'width': '1000px' }, 1000).promise()).then(function(){
return Promise.resolve($('#art2').animate({ 'width': '1000px' }, 1000).promise());
}).then(function(){
return Promise.resolve($('#art3').animate({ 'width': '1000px' }, 1000).promise());
});
Normal methods can also be wrapped in Promises
.
new Promise(function(fulfill, reject){
//do something for 5 seconds
fulfill(result);
}).then(function(result){
return new Promise(function(fulfill, reject){
//do something for 5 seconds
fulfill(result);
});
}).then(function(result){
return new Promise(function(fulfill, reject){
//do something for 8 seconds
fulfill(result);
});
}).then(function(result){
//do something with the result
});
The then
method is executed as soon as the Promise
finished. Normally, the return value of the function
passed to then
is passed to the next one as result.
But if a Promise
is returned, the next then
function waits until the Promise
finished executing and receives the results of it (the value that is passed to fulfill
).
It sounds like you're not fully appreciating the difference between synchronous and asynchronous function execution.
The code you provided in your update immediately executes each of your callback functions, which in turn immediately start an animation. The animations, however, execute asyncronously. It works like this:
setTimeout
with a function containing the next animation step and a delaysetTimeout
executes This continues until the last step in the animation completes. In the meantime, your synchronous functions have long ago completed. In other words, your call to the animate
function doesn't really take 3 seconds. The effect is simulated with delays and callbacks.
What you need is a queue. Internally, jQuery queues the animations, only executing your callback once its corresponding animation completes. If your callback then starts another animation, the effect is that they are executed in sequence.
In the simplest case this is equivalent to the following:
window.setTimeout(function() {
alert("!");
// set another timeout once the first completes
window.setTimeout(function() {
alert("!!");
}, 1000);
}, 3000); // longer, but first
Here's a general asynchronous looping function. It will call the given functions in order, waiting for the specified number of seconds between each.
function loop() {
var args = arguments;
if (args.length <= 0)
return;
(function chain(i) {
if (i >= args.length || typeof args[i] !== 'function')
return;
window.setTimeout(function() {
args[i]();
chain(i + 1);
}, 2000);
})(0);
}
Usage:
loop(
function() { alert("sam"); },
function() { alert("sue"); });
You could obviously modify this to take configurable wait times or to immediately execute the first function or to stop executing when a function in the chain returns false
or to apply
the functions in a specified context or whatever else you might need.
I believe the async library will provide you a very elegant way to do this. While promises and callbacks can get a little hard to juggle with, async can give neat patterns to streamline your thought process. To run functions in serial, you would need to put them in an async waterfall. In async lingo, every function is called a task
that takes some arguments and a callback
; which is the next function in the sequence. The basic structure would look something like:
async.waterfall([
// A list of functions
function(callback){
// Function no. 1 in sequence
callback(null, arg);
},
function(arg, callback){
// Function no. 2 in sequence
callback(null);
}
],
function(err, results){
// Optional final callback will get results for all prior functions
});
I've just tried to briefly explain the structure here. Read through the waterfall guide for more information, it's pretty well written.
your functions should take a callback function, that gets called when it finishes.
function fone(callback){
...do something...
callback.apply(this,[]);
}
function ftwo(callback){
...do something...
callback.apply(this,[]);
}
then usage would be like:
fone(function(){
ftwo(function(){
..ftwo done...
})
});
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