The
JavaScript
Event Loop


Event Loop


What do we know about JavaScript?
Event Loop


Rumor has it that JavaScript is...

- Great for serving many Concurrent connections
- Single threaded
- Can be blocking and Non-blocking simultaneously…
- Asynchronous by nature
- and Async is so darn fast!
Event Loop


But what is JavaScript actually made of?
- a runtime like V8 (heap/stack)
- a call stack
- a callback queue
- an event loop
-
Browser - web api's (DOM, ajax, setTimeout...)
-
Node.js - bindings (file-system, network, other...)

Event Loop


The browser and Node
are NOT Single threaded,
but JavaScript is!

Event Loop


JavaScript is Single threaded
- Benefits: no locks, race conditions and threading overhead.
- Implications: a single thread === a single call stack
- Which means - JavaScript can play one thing at a time.


Event Loop


So what is this call stack?
The call stack determines
where we are in the program.
- When we run a function,
we push it to the stack.
- When a function returns,
we pop it off the top of the stack.


Event Loop


The call stack
When errors occure,
we can examine the call stack
in the console.
- We see which functions have been called, and when that error happened.

Event Loop


So JavaScript is actually blocking?
Well – it depends on the code we execute in the call stack…
for( let i = 0 ; i < 1000000000 ; i++ ) {
//nothing will run until this loop ends…
}
const now = new Date().getTime();
while (new Date().getTime() < now + 10000){
//the thread is blocked for 10 seconds…
}
Event Loop


So be careful, you only have
a single thread, try not to kill it...

Event Loop


-
The Call Stack is single threaded
-
async io calls run in other threads
-
Then added to the callback queue
-
Then executed in the stack once it is available

What about
Those callbacks
then?
Event Loop


Node.js has a very Similar Flow



Event Loop


The difference is exponential

Event Loop


The event loop scales really nice with all those Async i/o calls...

Event Loop


But what about those blocking operations in the call stack?

Event Loop


Classic example will be sorting very big data-structures

How can we make sure those will not to block the call stack?
Event Loop


Make it land in the callback queue
We can break down a long process to small "async"
chunks and use setTimeout() to avoid blocking
function longProcess(array,render){
const items = [...array]; //clone the array
const iterator = ()=> {
const item = items.shift();
render(item);
if (items.length > 0) setTimeout(iterator, 0);
}
setTimeout(iterator, 0);
}
Between each process, we call setTimeout with 0 milliseconds delay,
giving the call stack a chance to execute and clear
Event Loop


SetTimeout() sets a minimum time
If the call-stack is not empty, it will finish running the code first
and only then process the callback queue…

Event Loop


So we can use setTimeout(func,0) to breakdown
long JS computation into small non-blocking operations
setTimeout(func,0)
The recommended way is to use setImmediate(func);
suggested by Microsoft and implemented by Node.js
setImmediate(func)
for all browsers and old 0.9 Node.js
Shim - setImmediate demo
Event Loop

- Use setImmediate
to queue the function at the end of I/O callback queue.
- Use process.nextTick()
to queue the function at the beginning of the callback queue.
setImmediate() vs process.nextTick()

So when breaking up a long running job using an iterator,
you want to use setImmediate rather than process.nextTick
otherwise any I/O callbacks wouldn't get the chance to run between iterations.
Event Loop

Pop quiz...

What will we see in the console?
setTimeout( ()=> console.log('hello') , 0);
[...'world'].map( str => console.log(str) );
console.log('!');
console.log('Kick-off');
setTimeout(()=> console.log('timeout') , 0);
Promise.resolve()
.then(()=> console.log('promise 1') )
.then(()=> console.log('promise 2') )
.then(()=> console.log('promise 3') )
console.log('The end!');
console.log('Kick-off');
setImmediate(()=> console.log('setImmediate'));
Promise.resolve()
.then(()=> console.log('promise 1') )
.then(()=> console.log('promise 2') )
.then(()=> console.log('promise 3') )
console.log('The end!');
console.log('Kick-off');
process.nextTick(()=> console.log('nextTick'));
Promise.resolve()
.then(()=> console.log('promise 1') )
.then(()=> console.log('promise 2') )
.then(()=> console.log('promise 3') )
console.log('The end!');
The JavaScript Event Loop
By Yariv Gilad
The JavaScript Event Loop
- 2,448