I am new(2 days!!) to the world of JavaScript and my only prior coding experience is in Java where execution of statements takes place sequentially. I understand that or at least I've read that JavaScript is asynchronous which means that if there is a statement that takes a long time to execute, the next statement is executed without holding up the program for the first statement. I came across callbacks(a lot actually!!) but I couldn't see how they could be used to determine the order of execution. I wrote a piece of code just to understand how it could be done and I sure could use some help.
console.log("Beginning");
function Test(callback){
setTimeout(function(callback){
console.log("Something that takes a lot of time");
},5000);
callback();
}
function tstCallBack(){
console.log("Should come last");
}
Test(tstCallBack);
What I want is for the output to display -
Beginning
Something that takes a lot of time
Should come last
But the output I am getting is -
Beginning
Should come last
Something that takes a lot of time
Is there anything I can do to get the output in the way I want it?
A lot of what you've said is wrong. JavaScript is sequential in the same way as Java, but asynchronous calls are made more often. If you want your callback to be called after the long thing, you must call it after the long running program. Like so -
Place the callback inside
setTimeout
and not outside as thecallback
will be executed first before the setTimeout does as javascript won't wait forsetTimeout
execution(as JS is synchronous by nature) and executes the next line and hence you won't get the desired output.Demo
Let's clear some things up in what you said:
This is not how it works. A given function is either asynchronous or its synchronous by design. It has absolutely nothing to do with how long it takes to execute. You can have a very quick async function or a very long synchronous function. What determines whether the function is asynchronous or not is how it is designed. If it uses async I/O or timers or any other async infrastructure, then at least some of the execution of the function is asynchronous. That means that some of the function will finish LATER and some of the code right after this function call will execute BEFORE the async portion finishes.
Callbacks are used to notify the calling code when some asynchronous operation has completed. This can be used either to consume the result of the asynchronous operation or can be used to execute the next piece of code that wants to run in sequence after the async operation has finished.
In your code example, if you want the desired sequence, then you must call the callback inside the
setTimeout()
callback so that it gets called AFTER thesetTimeout()
called executes, thus giving you the desired sequence.You also have to remove the
callback
argument to thesetTimeout
callback. That callback is not passed with that argument so declaring it there is just wrong. It can be accessed directly from the parent function via a closure as shown here:This will generate a sequence in the console of:
Conceptually, the Javascript engine runs a single thread and that single thread uses an event queue. So, in your function above, this is what happens.
console.log("Beginning");
is executed.Test(tstCallback)
is called.Test()
function, a timer is scheduled. This registers a timer internal to the JS engine.Test()
continues,console.log("After Setting Timer");
is executed and then that function finishes.console.log("Something that is asynchronous");
line and then callscallback()
.tstCallback
function is then called andconsole.log("Should come last");
is executed.There are a number of very good references on how Javascript handles asynchronous operations:
How does JavaScript handle AJAX responses in the background?
How Javascript Timers Work
Do I need to be concerned with race conditions with asynchronous Javascript?
I have modified your code as below to get the desired output.
setTimeout takes a callback function that will be executed after the specified time interval
The use of setTimeout is the asynchronous part. When the above code is executed,first the "Begining" console statement is printed and then the Test function is called passing in a function that needs to be executed asynchronously after 500ms .