What is “Event Loop” (Javascript)?
#event loop
Before we start to find out what event loop is
What are the main stuffs of Javascript?
- Call Stack: Stacks of frames
- Task queue: waiting queues to be done (Async functions such as callbacks will be stacked to task queue)
- Heap Memory: Memory space without structured
So, after all call stack jobs are done, the things which were stacked in Task Queue will be done when the call stack is empty.
As a result, all handles in event cannot be done first.
How’s asynchronous working in JS
Javascript: Single Threaded
That means, until one function is fully executed, another function cannot block the ongoing function.
Then, how javascript handle asynchronous functions?
Javascript handles async tasks like this.
while(queue.waitForMessage()){ queue.processNextMessage(); }
Javascript keeps waiting until they have a message on the queue.
After that, if
queue.waitForMessage()
is true (that means queue got message), javascript execute the message.If some messages were stacked in the queue before, that message will be executed when all other before messages were done.
Let’s say we have a javascript code like this!
console.log('Hi!'); // synchronous setTimeout(() => { console.log('Yay!'); }, 4000); // asynchronous console.log('Bye!'); // synchronous
That console logs which will show “Hi!” and “Bye!” will be done synchronously.
As a result,
console.log('Hi!');
will be the first one which will be stacked on the call stack.If that console log will be done, it will be disappeared by popping from call stack.
As a result, the console will say “Hi!”.
After that,
setTimeout
function will be on the call stack.setTimeout
function will be popped from call stack.
But, nothing will be happened on the console. You will see “Bye!” because console.log function was on the call stack and was popped.After 4 seconds, console says “Yay!”
Why this is happening like this?
We expected this situations.
Hi! → Wait 4 seconds → Yay! → Bye
Here, we can see Event Loop.
Event loop’s main role is watching the call stack.
It means, the events which were stacked in event loop keep watching call stack.
If the call stack is empty, the events which were in event loop will be stacked in call stack.
And then, the events will be executed which were in the event loop which did nothing.
Let’s come back to the code above.
After all the synchronous functions (which is console.logs) will be popped from call stack (which means all sync functions are executed), the callback function of
setTimeout
will be executed after 4000ms which was in the event loop.Then, what if setTimeout function has 0ms delay time?
console.log('Hi!'); // synchronous setTimeout(() => { console.log('Yay!'); }, 0); // asynchronous console.log('Bye!'); // synchronous
Same! The result is same!
Hi! -> Bye! -> Yay!
The reason is simple and same.
Delaying 0ms doesn’t make async callback as sync.
Web API
The web APIs are asynchronous.
setTimeout function is the web api. So it was executed lastly.
fetch
function will be the example of web api.console.log('Hi! again.'); fetch(.......).then(() => { console.log('Fetched!'); }); console.log('Bye! again.');
Above code is the example code of using fetch function.
Like above, the result will be like this.
Hi! again. -> Bye! again. -> Fetched!
First, console log which logs “Hi! again” will be on the call stack and will be popped out and will be executed.
After that, fetch function will be stacked on the call stack, fetch which is web api will be working until XHR will be done.
But, in the call stack, fetch function will be popped out before XHR will be done.
After that, console log which logs “Bye! again” will be stacked and popped.
After XHR was done, the callback function of fetch (console log Fetched!) will be on the task queue and event loop will know the call stack is empty.
That call back function will be stacked on the call stack.
And, lastly,
console.log('Fetched!');
will be executed.Let’s see the example code which is little bit more difficult.
console.log('Oops!'); button.addEventListener('click', () => { console.log('hehe did you click me?'); }); setTimeout((() => { console.log('I waited 3000ms!'); }), 3000); console.log('Yay!');
Can you expect how above code will be done?
The result is like this!
Oops! Yay! I waited 3000ms!
hehe did you click me?
will be only executed when someone clicked the button.So, that will be executed after “Oops!” and “Yay!”
Because it uses web api. Web api is on the task queue under the event loop, after all the synchronous functions are executed, it will be stacked on call stack and will be popped out.
But if we click that button in 3000ms, button click event’s console log will be shown before “I waited 3000ms!”.
By the way, that 3000ms means the exact 3 seconds?
The answer is no.
Because that 3000ms means the least delay time will be 3 seconds before all the functions are executed.
So, if we set 0ms as setTimeout’s second parameter, setTimeout will be executed asynchronously.
The reason is the minimum waiting time is 0ms. It doesn’t mean that call back will be executed in 0ms.
It is asynchronous function, so it will be run after it will be popped out from task queue.
Benefits of async functions
So, is web browser’s rendering is asynchronous?
Yes! Because rendering itself is one of web apis.
Browser rendering itself is asynchronous event.
We also call it as “render queue”. Render queue has priority than other async web apis. (but it has less priority than sync functions which will be stacked in call stack)
So, each 16ms, render will be stacked in queue, after stack is empty, browser will render.
But, if we stack many sync events to call stack, the browser’s rendering will be delayed.
Because, call stack will run other sync functions before handling browser rendering.
So in that case, browser will not work.
If we handle very huge calculation stuffs as sync functions, browser will be stopped.
The reason why is the browser render function will be delayed until all other huge calculation sync functions will be done.
But, if we handle some huge stuffs as async functions, browser will be working properly.
Because, render functions has priority than other async functions, so render function can be done between other async functions. (each 16ms)
Don't block the event loop!
Do not block the event loop!
That means eventually we have to deal with heavy stuffs as async functions. (not handle them as sync functions)
Async functions won’t block event loop.
They will be run on the backside of javascript, and when they were done, their callbacks will be stacked on call stack.
Web API and Javascript Engine
Such as console.log() functions are synchronous functions. (native javascript functions)
They are javascript function itself. So, they are not events.
But in real world web applications, we handle a lot of events.
We cannot make real world web applications by only using looping arrays or calculations like plus, minus.
Then, how so these web api events can be run?
The answer is in javascript engine.
For example, there is V8 engine from google.
Now, Chrome browser uses V8 javascript engine.
In the above link, we can find out the details of javascript engine.
Events which are run on these javascript engines are all asynchronous functions.
The functions that are run with browser API.
SetTimeout function is also executed on the javascript engine.
And also event listeners too.
It would be helpful to understand event loop if we understand these javascript engines.