setTimeout and setInterval
setTimeout and setInterval are the most common macrotask creators.
setTimeout
Schedules a function to run after a specified delay.
console.log('Start');
setTimeout(() => {
console.log('Timeout');
}, 1000);
console.log('End');
// Output: Start, End, Timeout (after 1 second)
Important: The delay is a minimum, not a guarantee. The callback won't run until:
- The specified time has elapsed
- The call stack is empty
- All microtasks have been processed
// Even with 0ms, it doesn't run immediately
setTimeout(() => console.log('timeout'), 0);
console.log('sync');
// Output: sync, timeout
setInterval
Repeats a function at specified intervals.
let count = 0;
const interval = setInterval(() => {
console.log(`Count: ${count}`);
count++;
if (count > 5) {
clearInterval(interval); // Stop after 5
}
}, 1000);
Timing Issues
// setInterval doesn't wait for callback to finish
setInterval(() => {
// If this takes 200ms, next fires at 1000ms (not 1200ms)
console.log('tick');
}, 1000);
// Better: use setTimeout recursively
function repeat() {
console.log('tick');
setTimeout(repeat, 1000); // Waits for callback to finish
}
repeat();
Task Scheduling
JavaScript provides several ways to schedule tasks for later execution.
setTimeout(fn, 0)
Defers execution until the call stack is empty.
// Useful for breaking up long-running tasks
function processData(data) {
// Process first batch synchronously
processBatch(data.slice(0, 100));
// Defer remaining batches
setTimeout(() => {
processBatch(data.slice(100, 200));
setTimeout(() => {
processBatch(data.slice(200));
}, 0);
}, 0);
}
requestAnimationFrame
Fires before the next browser paint.
function animate() {
// Update animation
element.style.left = `${x}px`;
x++;
if (x < 100) {
requestAnimationFrame(animate); // ~60fps
}
}
requestAnimationFrame(animate);
Comparison
| Method | Queue | Priority | Use Case |
|---|---|---|---|
| setTimeout | Macrotask | Low | General deferral |
| setInterval | Macrotask | Low | Repeated execution |
| requestAnimationFrame | Macrotask | Before paint | Animations |
| queueMicrotask | Microtask | High | Immediate post-sync |
Preventing Starvation
// Bad: can starve macrotasks
function heavyTask() {
// Process items
processItems();
queueMicrotask(heavyTask); // Keeps adding microtasks
}
// Good: yield to macrotasks
function heavyTask() {
processItems();
setTimeout(heavyTask, 0); // Allows macrotasks to run
}
Rendering and Tasks
The browser rendering pipeline is interleaved with task processing.
Rendering Pipeline
- JavaScript → Execute event handlers, style calculations
- Style → Compute final styles
- Layout → Calculate geometry
- Paint → Draw pixels
- Composite → Layers combined
When Rendering Happens
The browser typically renders at ~60fps (every ~16.7ms). Rendering happens between macrotask processing.
// Browser checks if render is pending
// If yes, render before next macrotask
function eventLoop() {
while (queueIsNotEmpty) {
// Process one macrotask
task = dequeueMacrotask();
executeTask(task);
// Process all microtasks
drainMicrotaskQueue();
// Check if render is pending
if (renderIsPending) {
render();
}
}
}
requestAnimationFrame Timing
// rAF fires before render
requestAnimationFrame(() => {
console.log('rAF'); // Before paint
});
setTimeout(() => {
console.log('timeout'); // After paint
}, 0);
// Output: rAF, timeout
Layout Thrashing
// BAD: causes multiple reflows
for (let i = 0; i < 100; i++) {
element.style.width = `${i}px`; // Triggers layout
console.log(element.offsetWidth); // Forces layout read
}
// GOOD: batch reads and writes
const width = element.offsetWidth; // Read once
for (let i = 0; i < 100; i++) {
element.style.width = `${width + i}px`; // Write
}
Practice Problems
Create a reusable React component implementing Macrotasks. 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 Macrotasks using React Testing Library.
Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility testsOptimize Macrotasks 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 a macrotask?
2. Why might setTimeout(fn, 0) delay more than expected?
3. When does requestAnimationFrame fire?
4. What is layout thrashing?
Flashcards
Question
What is a macrotask?
Click to reveal answer
Answer
A task from the macrotask queue (setTimeout, setInterval, DOM events) that is processed one per event loop iteration, after all microtasks.
Question
How does setTimeout(fn, 0) work?
Click to reveal answer
Answer
It defers execution until the call stack is empty and all microtasks are processed. The 0ms is a minimum, not exact timing.
Question
What is the difference between setTimeout and setInterval?
Click to reveal answer
Answer
setTimeout runs once after a delay. setInterval repeats at intervals, but doesn't wait for the callback to finish before scheduling the next.
Question
When does requestAnimationFrame fire?
Click to reveal answer
Answer
Before the next browser paint, making it ideal for smooth animations at ~60fps.
Question
What is Macrotasks?
Click to reveal answer
Answer
Macrotasks is a key concept in frontend development.
Revision Notes
Key Takeaways
- 1.Macrotasks are processed one per event loop iteration
- 2.All microtasks run before any macrotask
- 3.setTimeout(fn, 0) is a minimum delay, not exact
- 4.requestAnimationFrame fires before the next paint
- 5.Layout thrashing causes performance issues - batch reads and writes
Interview Tips
- •Explain why setTimeout(fn, 0) doesn't execute immediately
- •Compare setTimeout vs setInterval timing behavior
- •Discuss when to use requestAnimationFrame vs setTimeout
- •Explain layout thrashing and how to prevent it
Cheat Sheet
Macrotasks Cheat Sheet
Common Macrotasks
setTimeout()/setInterval()requestAnimationFrame()- DOM event handlers
fetch()response handling
Processing Order
- Synchronous code
- ALL microtasks
- ONE macrotask
- Check if render is pending
- Repeat
Timing
- setTimeout: minimum delay, not exact
- rAF: before next paint (~60fps)
- setInterval: doesn't wait for callback
Prevention
- Avoid layout thrashing (batch reads/writes)
- Use setTimeout for long tasks to yield control