In JavaScript, the event loop is a mechanism that allows asynchronous code to run without blocking the main thread. It continuously monitors the call stack and the task queue for new tasks and schedules them to run in the appropriate order.
What is a call stack?
The call stack is a data structure used by JavaScript runtime to keep track of the sequence of function calls in the execution context. Every time a function is called, a new frame is pushed onto the top of the stack, and when a function completes its execution, the frame is popped off the top of the stack.
When a JavaScript program starts executing, a global execution context is created, and its corresponding frame is pushed onto the call stack. As functions are called, new frames are pushed onto the stack, and when a function returns, its frame is popped off the stack.
For example, consider the following code:
function greet(name) { console.log(`Hello, ${name}!`); } function sayHello() { console.log("Calling greet function..."); greet("John"); } console.log("Starting program..."); sayHello(); console.log("Program completed.");
Here's what happens when this code is executed:
- The global execution context is created, and its corresponding frame is pushed onto the call stack.
- The console.log statement is executed, printing "Starting program..." to the console.
- The sayHello function is called, and its corresponding frame is pushed onto the stack.
- The console.log statement inside sayHello is executed, printing "Calling greet function..." to the console.
- The greet function is called from within sayHello, and its corresponding frame is pushed onto the stack.
- The console.log statement inside greet is executed, printing "Hello, John!" to the console.
- The greet function completes its execution and its frame is popped off the stack.
- Execution returns to sayHello, and its frame is still on top of the stack.
- The sayHello function completes its execution and its frame is popped off the stack.
- Execution returns to the global context, and its frame is now on top of the stack.
- The console.log statement is executed, printing "Program completed." to the console.
- The global context completes its execution and its frame is popped off the stack.
What is Task Queue?
The task queue is a data structure that manages the execution order of tasks. A task is any unit of work that needs to be executed, such as an event handler, a function call, or a timer callback. When a task is added to the task queue, it is processed by the event loop and executed by the JavaScript engine.
The task queue is divided into two types of tasks: macro tasks and micro tasks. Macro tasks are tasks that are queued by the browser or the JavaScript engine, such as user input events, network requests, and timer callbacks. Micro tasks, on the other hand, are tasks that are queued by the JavaScript engine itself, such as Promise callbacks, mutation observers, and queueMicrotask.
Microtasks are executed before macrotasks in the event loop. When a microtask is added to the microtask queue, it is executed before any other task in the event loop, including any pending macrotasks. This means that if there are multiple microtasks in the queue, they will be executed one after the other before any macrotasks are processed.
Here's an example of how the event loop works in JavaScript:
console.log('start'); setTimeout(() => { console.log('setTimeout 1'); }, 0); Promise.resolve().then(() => { console.log('Promise 1'); }); setTimeout(() => { console.log('setTimeout 2'); }, 0); Promise.resolve().then(() => { console.log('Promise 2'); }); console.log('end');
- The first console.log statement is executed synchronously, printing "start" to the console.
- The first setTimeout callback is added to the task queue with a delay of 0 milliseconds.
- The first Promise is resolved, and its callback is added to the microtask queue.
- The second setTimeout callback is added to the task queue with a delay of 0 milliseconds.
- The second Promise is resolved, and its callback is added to the microtask queue.
- The last console.log statement is executed synchronously, printing "end" to the console.
- The event loop begins processing the microtask queue, starting with the first Promise callback. It prints "Promise 1" to the console.
- The event loop continues processing the microtask queue, running the second Promise callback. It prints "Promise 2" to the console.
- The event loop begins processing the task queue, starting with the first setTimeout callback. It prints "setTimeout 1" to the console.
- The event loop continues processing the task queue, running the second setTimeout callback. It prints "setTimeout 2" to the console.
Comments
Post a Comment