typescriptintermediate

Event Loop and Timers

Understand Node.js event loop phases with setTimeout, setInterval, setImmediate, and process.nextTick.

typescript
// Event loop order:
// 1. process.nextTick (microtask)
// 2. Promises (microtask)
// 3. setTimeout/setInterval (timers phase)
// 4. setImmediate (check phase)
// 5. I/O callbacks

// Demonstrate execution order
console.log('1. Synchronous');

process.nextTick(() => console.log('2. nextTick'));

Promise.resolve().then(() => console.log('3. Promise'));

setTimeout(() => console.log('4. setTimeout 0'), 0);

setImmediate(() => console.log('5. setImmediate'));

console.log('6. Synchronous end');

// Output order: 1, 6, 2, 3, 4, 5

// Debounce with setTimeout
function debounce<T extends (...args: any[]) => void>(
  fn: T,
  delay: number
): (...args: Parameters<T>) => void {
  let timer: ReturnType<typeof setTimeout>;
  return (...args: Parameters<T>) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
}

// Recurring task with setInterval
function pollEndpoint(url: string, intervalMs: number): () => void {
  const timer = setInterval(async () => {
    try {
      const res = await fetch(url);
      console.log(`Poll ${url}: ${res.status}`);
    } catch (e) {
      console.error(`Poll error: ${(e as Error).message}`);
    }
  }, intervalMs);

  // Return cleanup function
  return () => clearInterval(timer);
}

// Delay utility
const delay = (ms: number) => new Promise<void>(r => setTimeout(r, ms));

// Retry with backoff
async function retry<T>(
  fn: () => Promise<T>,
  maxRetries: number = 3,
  baseDelay: number = 1000
): Promise<T> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      const wait = baseDelay * Math.pow(2, i);
      console.log(`Retry ${i + 1}/${maxRetries} in ${wait}ms`);
      await delay(wait);
    }
  }
  throw new Error('Unreachable');
}

// Schedule work after I/O
import { readFile } from 'fs/promises';
readFile('./package.json', 'utf-8').then(() => {
  // Runs after I/O
  setImmediate(() => console.log('After I/O: setImmediate'));
  setTimeout(() => console.log('After I/O: setTimeout'), 0);
});

Use Cases

  • Understanding async execution order
  • Implementing retry with backoff
  • Polling and scheduled tasks

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.