-
Javascript runtime environment is the big picture for a javascript program execution, runtime environment is where your javascript code will be executed by utilizing a set of components together.
-
Javascript runtime environment is the reason why we can write asynchronous code given that javascript is single threaded and synchronous, runtime environment will provide us with apis to be able to write asynchronous code.
- Javascript Engine
- Environment Apis, Examples: [Browser Web Apis, Node Server Apis, ... etc]
- Task Queue
- Event Table
- Event Loop
Javascript runtime environment is responsible for providing apis to interact with the host application
-
Examples:
- Browser runtime environment will provide us with Wep Apis like
DOM
,XMLHttpRequest
,setTimeout
,setInterval
... etc - Node runtime environment will provide us with
FileSystem
,http
... etc
- Browser runtime environment will provide us with Wep Apis like
Task Queue, Event Table and Event loop are the three components that give us asynchronous capability in javascript.
-
Whenever javascript engine finds a method from runtime environment asynchronous api like
setTimeout
, it will pop it from execution stack and send it toEvent Table
inside runtime environment, this way execution of synchronous code will not be blocked, and javascript engine will be able to execute next execution context in execution call stack -
setTimeout
will stay inEvent Table
until specified delay is finished and then it will be sent toTask Queue
. -
Event Loop
will keep checking bothExecution Call Stack
in engine andTask Queue
, and whenever there is a queued task inTask Queue
it will push it toExecution Call Stack
if it is empty. -
It is very important to understand that
Event loop
cannot push any task toExecution Call Stack
until it is empty.
1 console.log('start');
2 const startTime = new Date();
3 setTimeout(function myCallbackFunction() {
4 const endTime = new Date();
5 const timeDiff = endTime.getTime() - startTime.getTime();
6 console.log(`${timeDiff / 1000} seconds`);
7 console.log('setTimeout callback is executed');
8 }, 1000);
9 console.log('end');
// start
// end
// 1.001 seconds
// setTimeout callback is executed
Now lets see how runtime environment components will work together for the above asynchronous code snippet:
- Line 1: Engine will push
console.log('start')
to execution call stack and then will pop it once finished - Line 2: Engine will push
new Date()
to execution call stack and then will pop it once finished - Line 3: Engine will push
setTimeout
to execution call stack and then will realize that it is a runtime asynchronous api, so it will pop it and send it to runtime environment that will insert it inEvent Table
- Line 9: Engine will push
console.log('end')
to execution call stack and then will pop it once finished - Now engin's execution call stack is empty and nothing is happening
- 1 second passed since we called Line 3, so runtime environment will remove
setTimeout
fromEvent Table
and queuemyCallbackFunction
task insideTask Queue
Event Loop
will check if any task is there inTask Queue
and will push that task to execution call stack only if it is empty, so it will be pushed immediately.- Now
myCallbackFunction()
is in execution call stack - Line 4: Engine will push
new Date()
to execution call stack and then will pop it once finished - Line 5: Engine will push
startTime.getTime()
and pop it then pushendTime.getTime()
and pop it - Line 6: Engine will push
console.log(
${timeDiff / 1000} seconds);
and pop it - Line 6: Engine will push
console.log('setTimeout callback is executed');
and pop it
console.log('start');
const startTime = new Date();
setTimeout(function myCallbackFunction() {
const endTime = new Date();
const timeDiff = endTime.getTime() - startTime.getTime();
console.log(`${timeDiff / 1000} seconds passed`);
console.log('setTimeout callback is executed');
}, 1000);
let i = 0;
while(true) {
if(i >= 10000000000) {
break;
}
i++;
}
console.log('end');
// start
// end
// 12.058 seconds passed!
// setTimeout callback is executed
Notice how in Example 18.1 myCallbackFunction
is delayed 12 seconds not 1 second as we passed in setTimeout
this is because myCallbackFunction
was in Task Queue
but Event Loop
was not able to push it in Execution Call stack, because it was not empty.
From this we can understand that the value we pass to setTimeout
is the minimum delay to the callback function not the exact one.