If someone who is not in the tech industry (a Muggle π) asks you what JavaScript is, could you define it? Well, you could say something like this:
"Javascript is an asynchronous, single-threaded and non-blocking language which uses some tools like a call stack, an event loop, a callback queue and some other APIs for concurrency".
But BRUUUH??!!
That sounds like a dangerous spell in Harry Potter that would send your enemy straight to hell, doesn't it? But don't worry, I don't like when people use some complicated words to say barely nothing either. So let's go through each of those bizarre words.
- Call stack: that is where our tasks (functions encountered in the code) are stacked. When we encounter a function, we push it to the stack and when we return from that function, we pop it off the stack (LIFO)
- Single-threaded: in simple words, JavaScript can only do one thing at a time (one call stack). One element (function) in the stack is executed at a time.
- Non-blocking: it means that whenever a "slow" task (I'll tell you what i mean by that later) is encountered in the call stack, it doesn't block the execution of the following tasks.
- Asynchronous: The non-blocking behavior we explained above is done by using asynchronous callbacks which means that we run the "slow" task, give it a callback (an action to do when it's done), and run that callback later.
- Callback queue: basically the place where the callbacks are queued (FIFO) waiting for their turn to be called by our MVP, the call stack π
- The famous Event Loop: that's what this whole article is about. Basically, it's the process of checking if the call stack is empty, and if so, taking off the first element (the first callback) in the queue (if it is not empty, of course π) and pushing it to the stack for it to be executed.
Easy Peasy, isn't it π?! NO?! Alright, I admit, that's a lot of words. So let's see a straightforward example to explain all of this.
Let's admit we're in a restaurant where some orders are already cooked and are quick to serve by the waitress, and some other are harder to make and are going to take time to be cooked by the chef (the "slow" tasks I was talking about π). We imagine that whatever the chef cooks, he puts it on his big table for the waitress to take it (It's my article, I do what i want, okay? π)
Now we suppose that our waitress has 3 orders on her list. The quick orders are represented in white and the "slow" ones are represented in blue. They are stacked in her list.
The order on the top of the list (a hamburger) is then served to client 4 and get's removed from the list when it's done
We can notice that the next order is a slow order. So the waitress gives it to the chef who cooks it, and puts the bowl of cooked salad on his table, for the waitress to serve it later.
Meanwhile, the waitress takes care of the next order (a cup of juice) which is quick, and serves it to the client 4 (he's quite hungry π )
When it's done, the waitress notices that her list is empty. So she checks the chef's table to see if there is any meal on it.
If so, she takes that meal, and serves it the corresponding client (in this case, she serves a delicious bowl of salad the client 3)
Her list being still empty, she checks the chef's table once again and see's that there's nothing on it. Thus, she can clock out and go home π.
That's it!! That's how JavaScript works. You still can't make the connection between the example and the weird words above π©? Alright, let's see, with the same animation, how the following code is going to be executed.
console.log("Hello!");
setTimeout(function cb() {
console.log("Slow!!");
}, 7000);
console.log("Bye!");
First of all, let's place our weird words to where they belong in the animation
Now let's see how it works
- The
main()
function specified here is just the main thread of our code. - Each function is pushed to the stack when it is called, and popped off it when it returns something.
- Our slow function (
setTimeout()
) is not handled by the javascript engine, but by some WebAPIs in the browser which will push the resulting callback into the queue when it's done. - Meanwhile, the functions in the stack continue to get executed. Whenever the stack is empty, the event loop checks if the callback queue is empty, takes the first element in it (our callback function) and push it to the call stack
- The execution continues until there's nothing left in the call stack or in the callback queue.
See? It's not that complicated, right?
I hope this article helped you understand better the famous event loop and made you feel better with javascript. It is fundamental to understand these concepts in order to avoid some strange behaviors when you write asynchronous functions. If it still seems confusing to you, I recommend this excellent video of Philip Roberts explaining it:
Feel free to reach out to me if you have any questions:
- Github: nushen96
- Twitter: papidiagne30
Peace out!! βπΎ
Top comments (4)
I have question related to Promise.all() along with Web API.
So for example if I pass 100 requests into this Promise.all, then how exactly Web API will process it.
I mean will it create 100 parallel sub web api threads or how is it going to work.
Promise.all() takes promises as input, and just returns another promise if that happens. So your 100 promises will still be treated in the browser, independantly. And when they all resolve, the promise returned by Promise.all() resolves.
I don't understand one thing so I'm going to ask it.
Does the WebAPI calls and resolves our function and push the result to call stack? Or does it just waits for call stack to be clear and then hand over the function to it for normal execution?
Hey! Thanks for asking π.
The WebAPI resolves the function, and pushes its callback into the queue. The callbacks in that queue are not called until the call stack is empty, then they're pushed to it in order of arrival.