Event Loop is a mechanism in JavaScript responsible for executing code, collecting and processing events, and executing subprograms. It allows JavaScript to be single-threaded while still performing asynchronous operations like setTimeout, Promise, fetch, and others.
Main components:
Event Loop is a fundamental mechanism that makes asynchronous programming possible in JavaScript. Despite JavaScript being single-threaded, Event Loop allows it to perform non-blocking asynchronous operations.
Event Loop operates in the following cycle:
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
// Output: 1, 4, 3, 2The stack where function calls are stored:
function first() {
console.log('first'); // 1. console.log('first') executes
second(); // 2. second() call is added to the stack
}
function second() {
console.log('second'); // 3. console.log('second') executes
third(); // 4. third() call is added to the stack
}
function third() {
console.log('third'); // 5. console.log('third') executes
} // 6. third() completes and is removed from the stack
// 7. second() completes and is removed from the stack
// 8. first() completes and is removed from the stack
first(); // 0. first() call is added to the stackBrowser’s asynchronous APIs that handle timers, events, HTTP requests:
setTimeout(() => {
console.log('Timer completed');
}, 1000);
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data));Queue for tasks like setTimeout, setInterval, click events:
setTimeout(() => {
console.log('From callback queue');
}, 0);Queue for Promise, queueMicrotask:
Promise.resolve().then(() => {
console.log('From microtask queue');
});The microtask queue has higher priority:
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
Promise.resolve().then(() => console.log('4'));
setTimeout(() => console.log('5'), 0);
console.log('6');
// Output: 1, 6, 3, 4, 2, 5console.log('start');
setTimeout(() => console.log('setTimeout'), 0);
Promise.resolve()
.then(() => console.log('promise1'))
.then(() => console.log('promise2'));
console.log('end');
// Output: start, end, promise1, promise2, setTimeoutPromise.resolve()
.then(() => {
console.log('promise1');
return Promise.resolve();
})
.then(() => {
console.log('promise2');
});
Promise.resolve().then(() => console.log('promise3'));
// Output: promise1, promise3, promise2async function example() {
console.log('1');
await Promise.resolve();
console.log('2');
}
example();
console.log('3');
// Output: 1, 3, 2// ❌ Expectation: 1, 2, 3
// ✅ Reality: 1, 3, 2
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));// ❌ Bad - blocks Event Loop
function blockingOperation() {
while (true) {
// Infinite loop
}
}
// ✅ Good - breaking into chunks
function nonBlockingOperation() {
let i = 0;
function processChunk() {
const end = Math.min(i + 1000, data.length);
for (; i < end; i++) {
// Process data
}
if (i < data.length) {
setTimeout(processChunk, 0);
}
}
processChunk();
}Event Loop is the heart of asynchronous programming in JavaScript. Understanding how it works is crucial for writing efficient and predictable code, especially when working with timers, promises, network requests, and events.
What will be output to the console?
console.log('A');
setTimeout(() => console.log('B'), 0);
Promise.resolve().then(() => console.log('C'));
console.log('D');Answer: A, D, C, B
Explanation:
console.log('A') — synchronous call, executes immediatelysetTimeout(() => console.log('B'), 0) — asynchronous task goes to the Callback QueuePromise.resolve().then(() => console.log('C')) — microtask goes to the Microtask Queueconsole.log('D') — synchronous call, executes immediatelyconsole.log('C')console.log('B')What will be the order of output?
setTimeout(() => console.log('A'), 0);
Promise.resolve().then(() => {
console.log('B');
return Promise.resolve();
}).then(() => console.log('C'));
console.log('D');Answer: D, B, C, A
Explanation:
setTimeout(() => console.log('A'), 0) — task in the Callback QueuePromise.resolve().then(...) — microtask in the Microtask Queueconsole.log('D') — synchronous callWhat will this code output?
async function async1() {
console.log('A');
await async2();
console.log('B');
}
async function async2() {
console.log('C');
}
console.log('D');
setTimeout(() => console.log('E'), 0);
async1();
new Promise((resolve) => {
console.log('F');
resolve();
}).then(() => console.log('G'));
console.log('H');Answer: D, A, C, F, H, G, B, E
Explanation:
Understanding these tasks demonstrates a deep knowledge of Event Loop operation, task priorities, and asynchronous programming in JavaScript.
Want more articles to prepare for interviews? Subscribe to EasyAdvice, bookmark the site and improve yourself every day 💪