HomebaseWorks
Lesson 1 of 4

The event loop, modules and async code

Predict the order of logs, timers and promises, and load modules correctly in CommonJS and ES module projects.

EWritten by the HomebaseWorks editorial team · reviewed 26 Oct 2026

Node runs your JavaScript on a single thread. Slow work such as file reads, network calls and timers happens in the background, and their callbacks are queued to run when the thread is free. Knowing that queue order answers most output questions.

Advertisement

The order things run

  1. All synchronous code in the current script or callback.
  2. Microtasks: process.nextTick callbacks, then promise callbacks such as .then and code after await.
  3. The next event loop phase: expired timers, completed input and output callbacks, then setImmediate.

So with a setTimeout(fn, 0) and a resolved promise, the promise callback always runs first. A long synchronous loop blocks everything, including other users' requests on a server.

Async/await and errors

An async function always returns a promise. Inside it, await pauses only that function, not the whole program. Handle failures with try/catch:

async function loadUser(id) {
  try {
    const user = await db.find(id);
    return user;
  } catch (err) {
    logger.error(err);
    throw err;
  }
}

A rejected promise that nobody handles crashes current Node versions, so every promise chain needs a catch somewhere. To run independent calls together, use Promise.all; use Promise.allSettled when you need every result even if some fail.

CommonJS and ES modules

CommonJS uses require and module.exports. A common bug is writing exports = {...}, which rebinds a local variable and exports nothing. ES modules use import and export, and a file is treated as one when it ends in .mjs or package.json has "type": "module". In ES modules, relative imports need the file extension, as in import { sum } from './utils.js'.

npm basics

  • dependencies are needed at runtime; devDependencies are tools like test runners.
  • ^1.4.2 allows anything below 2.0.0; ~1.4.2 allows anything below 1.5.0.
  • Commit package-lock.json and use npm ci in builds for repeatable installs.

Habit: for any snippet, first list the synchronous lines, then the microtasks, then the timers. Write the order down before you run it.

Advertisement
Continue with Node.js4 lessons · 1 interview set · 1 test · 1 certificate
Not tested

More in Web and app