JAVASCRIPT
INTERVIEW
Browser JavaScript execution flow, as well as in Node.js, is based on an event loop. The event loop concept is very simple. There’s an endless loop, where the JavaScript engine waits for tasks, executes them, and then sleeps, waiting for more tasks.
The event loop is the secret behind JavaScript’s asynchronous programming.
Event Loop Visualization/Basic Architecture
Memory Heap
This is where all the memory allocation happens for your variables, that you have defined in your program.
Call Stack
This represents the single thread provided for JavaScript code execution. This is where all your javascript code gets pushed and executed one by one as the interpreter reads your program, and gets popped out once the execution is done. It is responsible for keeping track of all the operations in line to be executed. Whenever a function is finished, it is popped from the stack.
Browser or Web APIs
They are built into your web browser and are able to expose data from the browser and surrounding computer environment and do useful complex things with it. They are not part of the JavaScript language itself, rather they are built on top of the core JavaScript language, providing you with extra superpowers to use in your JavaScript code.
For example, the Geolocation API provides some simple JavaScript constructs for retrieving location data so you can say, plot your location on a Google Map. In the background, the browser is actually using some complex lower-level code (e.g. C++) to communicate with the device’s GPS hardware (or whatever is available to determine position data), retrieve position data, and return it to the browser environment to use in your code. But again, this complexity is abstracted away from you by the API.
Common browser APIs
- APIs for manipulating documents
- APIs that fetch data from the server
- Audio and Video APIs
- Client-side storage APIs
Event or Callback Queue
This is where your asynchronous code gets pushed to, and waits for the execution.
Event Loop
It has one simple job to monitor the call stack and the callback queue.
It keeps running continuously and checks the Main stack, if it has any frames to execute, if not then it checks Callback queue, if Callback queue has codes to execute then it pops the message from it to the Main Stack for the execution.
Job Queue or Microtask Queue
Apart from Callback Queue, browsers have introduced one more queue which is “Job Queue”, reserved only for new Promise() functionality. So when you use promises in your code, you add .then() method, which is a callback method. These thenable
methods are added to Job Queue once the promise has returned/resolved, and then gets executed.
Execution of async function in javascript
Whenever an async function is called, it is sent to a browser API. These are APIs built into the browser.
An example of this is the setTimeout method. When a setTimeout operation is processed, it is sent to the corresponding API which waits till the specified time to send this operation back in for processing.
This operation is then send to the callback queue. Hence, we have a cyclic system for running async operations in JavaScript. The language itself is single-threaded, but the browser APIs act as separate threads.
The event loop
facilitates this process. It has one simple job to monitor the call stack and the callback queue.
If the call stack is empty, the event loop will take the first event from the queue and will push it to the call stack, which effectively runs. If it is not, then the current function call is processed.
const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"), 500);
const baz = () => console.log("Third");
bar();
foo();
baz();
Output:
First
Third
Second
Why Job Queue or Microtask Queue
Micro-tasks has high priority in executing callbacks, if event loop tick comes to Micro-tasks, it will execute all the jobs in job queue first until it gets empty, then will move to callback queue.
- The primary reason for prioritizing the micro-task queue is to improve the user experience.
- Micro-tasks include mutation observer callbacks as well as promise callbacks.
Example:
console.log('Message no. 1: Sync');
setTimeout(function() {
console.log('Message no. 2: setTimeout');
}, 0);
var promise = new Promise(function(resolve, reject) {
resolve();
});
promise.then(function(resolve) {
console.log('Message no. 3: 1st Promise');
})
.then(function(resolve) {
console.log('Message no. 4: 2nd Promise');
});
console.log('Message no. 5: Sync');
// Message no. 1: Sync
// Message no. 5: Sync
// Message no. 3: 1st Promise
// Message no. 4: 2nd Promise
// Message no. 2: setTimeout
All thenable
callbacks of the promise are called first, then the setTimeout callback is called.
References:
Thanks for reading!!!
No comments:
Post a Comment