Microtask Queue
The microtask queue is a special queue with higher priority than the macrotask queue. All microtasks are processed before the next macrotask.
Key Characteristics
- Microtasks are processed after the current synchronous code completes
- ALL microtasks in the queue are drained before processing one macrotask
- If a microtask adds another microtask, it's processed in the same cycle
console.log('Start');
Promise.resolve().then(() => {
console.log('Microtask 1');
}).then(() => {
console.log('Microtask 2');
});
console.log('End');
// Output:
// Start
// End
// Microtask 1
// Microtask 2
When Microtasks are Created
Promise.then(),Promise.catch(),Promise.finally()queueMicrotask()MutationObserver(DOM changes)
// Using queueMicrotask()
console.log('Before');
queueMicrotask(() => {
console.log('Microtask');
});
console.log('After');
// Output: Before, After, Microtask
Promise Callbacks
Promise callbacks are the most common microtasks. Every .then(), .catch(), and .finally() callback becomes a microtask.
const promise = new Promise((resolve) => {
resolve(42);
});
// Each .then() creates a new microtask
promise
.then(value => {
console.log(value); // 42
return value * 2;
})
.then(value => {
console.log(value); // 84
});
// Output: 42, 84 (both are microtasks)
Promise Resolution Order
Promise.resolve()
.then(() => console.log('1'))
.then(() => console.log('2'));
Promise.resolve()
.then(() => console.log('3'))
.then(() => console.log('4'));
// Output: 1, 3, 2, 4
// First Promise: 1, then 2
// Second Promise: 3, then 4
// They interleave because microtasks are processed in order
Nested Promises
Promise.resolve()
.then(() => {
console.log('A');
// This nested promise also creates a microtask
return Promise.resolve().then(() => {
console.log('B');
});
})
.then(() => {
console.log('C');
});
// Output: A, B, C
Microtask vs Macrotask
Understanding the difference between microtasks and macrotasks is crucial for predicting async behavior.
Comparison
| Feature | Microtask | Macrotask |
|---|---|---|
| Priority | High | Low |
| Processing | ALL before next macro | ONE per cycle |
| Examples | Promise, queueMicrotask | setTimeout, setInterval |
| When processed | After sync code, before macros | After microtasks |
Execution Order Example
console.log('1 - sync');
setTimeout(() => {
console.log('2 - macrotask');
}, 0);
Promise.resolve().then(() => {
console.log('3 - microtask');
});
console.log('4 - sync');
// Output: 1, 4, 3, 2
// 1, 4: synchronous
// 3: microtask (higher priority)
// 2: macrotask (lower priority)
Nested Example
setTimeout(() => console.log('timeout1'), 0);
setTimeout(() => console.log('timeout2'), 0);
Promise.resolve()
.then(() => console.log('promise1'))
.then(() => console.log('promise2'));
// Output: promise1, promise2, timeout1, timeout2
// All microtasks process first, then all macrotasks
Common Mistake
// WRONG expectation: setTimeout with 0 runs first
setTimeout(() => {
console.log('setTimeout');
}, 0);
Promise.resolve().then(() => {
console.log('Promise');
});
// Actually outputs: Promise, setTimeout
// Microtasks ALWAYS run before macrotasks
Practice Problems
Create a reusable React component implementing Microtasks. Include proper state management and accessibility.
Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where neededWrite unit and integration tests for Microtasks using React Testing Library.
Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility testsOptimize Microtasks for performance. Consider memoization, code splitting, and bundle size.
Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysisQuiz
1. What is the priority of microtasks vs macrotasks?
2. Which of these creates a microtask?
3. What happens if a microtask adds another microtask?
4. What is the output? ```javascript Promise.resolve().then(() => console.log('a')); Promise.resolve().then(() => console.log('b')); ```
Flashcards
Question
What is a microtask?
Click to reveal answer
Answer
A high-priority task that is processed after synchronous code completes but before the next macrotask. Examples: Promise callbacks, queueMicrotask().
Question
When are microtasks processed?
Click to reveal answer
Answer
After the current synchronous code completes and before the next macrotask is processed. ALL microtasks in the queue are drained first.
Question
What is queueMicrotask()?
Click to reveal answer
Answer
A method that adds a callback to the microtask queue, ensuring it runs after the current code but before macrotasks.
Question
Does Promise.then create a microtask or macrotask?
Click to reveal answer
Answer
Microtask. All Promise callbacks (.then, .catch, .finally) are microtasks.
Question
What is Microtasks?
Click to reveal answer
Answer
Microtasks is a key concept in frontend development.
Revision Notes
Key Takeaways
- 1.Microtasks have higher priority than macrotasks
- 2.All microtasks are processed before the next macrotask
- 3.Promise callbacks are microtasks
- 4.Microtasks can add more microtasks, which process in the same cycle
- 5.Understanding microtasks is essential for predictable async behavior
Interview Tips
- •Explain why Promise.then runs before setTimeout even with 0ms delay
- •Trace through nested Promise chains to predict output order
- •Discuss how microtask processing can starve macrotasks
- •Use queueMicrotask() for guaranteed pre-macrotask execution
Cheat Sheet
Microtasks Cheat Sheet
What are they?
- High-priority tasks processed after sync code
- ALL microtasks run before the next macrotask
How to create
Promise.then()Promise.catch()Promise.finally()queueMicrotask()MutationObserver
Processing order
- Synchronous code
- ALL microtasks (in order added)
- ONE macrotask
- Repeat
Key rule
If a microtask adds another microtask, it processes in the same cycle.