Node.js
02 / 03

Event Loop & Async Programming

Node.js Event Loop & Async Programming

The event loop is the heart of Node.js. It enables non-blocking I/O operations despite JavaScript being single-threaded.

The Event Loop

// Event loop phases:
// 1. Timers (setTimeout, setInterval)
// 2. Pending callbacks (I/O callbacks)
// 3. Idle, prepare
// 4. Poll (retrieve new I/O events)
// 5. Check (setImmediate)
// 6. Close callbacks

console.log('1 - Start');

setTimeout(() => {
  console.log('2 - setTimeout');
}, 0);

setImmediate(() => {
  console.log('3 - setImmediate');
});

process.nextTick(() => {
  console.log('4 - nextTick');
});

Promise.resolve().then(() => {
  console.log('5 - Promise');
});

console.log('6 - End');

// Output:
// 1 - Start
// 6 - End
// 4 - nextTick
// 5 - Promise
// 2 - setTimeout
// 3 - setImmediate

Callbacks, Promises, Async/Await

// Callback pattern (old)
const fs = require('fs');

fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(data);
});

// Promise pattern
const fsPromises = require('fs/promises');

fsPromises.readFile('file.txt', 'utf8')
  .then(data => console.log(data))
  .catch(err => console.error(err));

// Async/await (modern)
async function readFile() {
  try {
    const data = await fsPromises.readFile('file.txt', 'utf8');
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}

// Promisify callback-based functions
const { promisify } = require('util');
const readFilePromise = promisify(fs.readFile);

async function read() {
  const data = await readFilePromise('file.txt', 'utf8');
  return data;
}

Error Handling

// Try-catch for sync errors
try {
  const data = JSON.parse(invalidJson);
} catch (error) {
  console.error('Parse error:', error);
}

// Try-catch for async/await
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Fetch error:', error);
    throw error;
  }
}

// Unhandled promise rejections
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
  // Application specific logging, throwing an error, or other logic here
});

// Uncaught exceptions
process.on('uncaughtException', (error) => {
  console.error('Uncaught Exception:', error);
  // Perform cleanup and exit
  process.exit(1);
});

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free