Javascript is a single threaded language. This means it has one call stack and one memory heap. As expected, it executes code in order and must finish executing a piece code before moving onto the next. It's synchronous, but at times that can be harmful. For example, if a function takes awhile to execute or has to wait on something, it freezes everything up in the meanwhile.
A good example of this happening is the window alert function. alert("Hello World")
You can't interact with the webpage at all until you hit OK and dismiss the alert. You're stuck.
So how do we get asynchronous code with Javascript then?
Well, we can thank the Javascript engine (V8, Spidermonkey, JavaScriptCore, etc...) for that, which has Web API that handle these tasks in the background. The call stack recognizes functions of the Web API and hands them off to be handled by the browser. Once those tasks are finished by the browser, they return and are pushed onto the stack as a callback.
Open your console and type window
then press enter. You'll see most everything the Web API has to offer. This includes things like ajax calls, event listeners, the fetch API, and setTimeout. Javascript uses low level programming languages like C++ to perform these behind the scenes.
Let's look at a simple example, run this code your console:
console.log("first")
setTimeout(() => {
console.log("second")
}, 1000)
console.log("third")
What did we get back?
first
third
undefined
second
Feels odd, right? Well, let's break this down line by line:
console.log("first")
is on the stack first, so it gets printed. Next, the engine notices setTimeout, which isn't handled by Javascript and pushes it off to the WebAPI to be done asynchronously. The call stack moves on without caring about the code handed off to the Web APIs and console.log("three")
is printed.
Next, the Javascript engine's event loop kicks in, like a little kid asking "Are we there yet?" on a road trip. It starts firing, waiting for events to be pushed into it. Since the setTimeout
isn't finished, it returns undefined
, as the default, well because it hasn't been given the value yet. Once the callback finally does hits we get console.log("second")
printed.
There's a really good site that slows this all down and shows this happening.
I suggest playing around in this sandbox to help solidify your understanding. It helped me get a feel for how asynchronous code can work with Javascript being single threaded.
Latest comments (47)
Can someone explain how we got an undefined?
I tried the code on my side and did not get undefined.
Why would it ?
Mastering this topic I considered as a fundamental of being a JavaScript developer, knowing more about JavaScript engine (compiler) , the browser mechanisms and critical rendering path ( CRP ) is very important thing! I advise the developers who want to be a rock in web development field, please go through this topics and learn them carefully and on top of that make a deep understanding of network layer like http requests, responses, cache, cookies, storage, sessions. And related stuff to a browser network.
Great explanation. I can easily imagine how js works while reading. Good job!
Nice article Brian with a practical example.
Here is another resource which can be a good primer for newbies in understanding why Javascript is called single-threaded language w3spot.com/2020/07/how-asynchronou....
I think you are wrong at this part
...we can thank the Javascript engine (V8, Spidermonkey, JavaScriptCore, etc...) for that, which has Web API...
.We don't thank JS Engine for that, because Web API is not part of the JS Engine but the
JS runtime environment provided by the Browser
, also provided by the browser is the JS Engine itself (V8 for Chrome) and Callback Queue and the Event Loop.The JS (V8) Engine is made up of Memory Heap & Call Stack.
Furthermore, the purpose of the JS engine is to parse/translate source code that we developers write into machine code that allows a computer to perform specific tasks on its hardware level.
Hi Brian,
Thanks for sharing this informative article with us
it helped me a lot.
Thank you for Nice explanations
I am curious to know, calling below in console give me a number instead of undefined. Can anyone tell me what number it refers to?
setTimeout(() => {
console.log("test")
}, 1000)
The Number is nothing but ID returned by the SetTimeout Method, Which is useful for clearing/Stopping the settimeout callback, before the callback triggering of give timeout value.
For Example:
clearTimeout(number_returned_by_set_timeout);
clearTimeout(1409)
Hey Brian, coming from the future here. I'm a little bit confused by this statement "Well, we can thank the Javascript engine (V8, Spidermonkey, JavaScriptCore, etc...) for that, which has Web API that handle these tasks in the background. ", if the task is handled in the background so it's mean if the javascript isn't single thread right? since the code is executed in the same time. thank you!
Great !
But can you explain why we get undefined in console!