Stop 04 · JavaScriptTopics · 16/36

Callbacks

Part of the Frontend Developer Roadmap

In short

Before Promises existed, JavaScript handled "do this, then that" by passing functions into other functions. These callbacks are still everywhere, from button clicks to array methods.

Functions passed as arguments to be executed later — the original pattern for async code in JS, still used everywhere (event handlers, array methods). Callbacks remain fundamental because browser events and many APIs are callback-driven, even when Promises and async/await provide cleaner composition for asynchronous workflows.

The jaadu mascot hands a sticky note to a busy receptionist juggling ringing phones.

Think of it like this

Leave your number for a call back

You call a coaching centre and every counsellor is busy. Instead of waiting on hold, you leave your number: "call me back when someone's free". A callback is that phone number: a function you hand over so it can be called later.

Watch it happen

Call stack with a delayed callback

push(global code)
global code

Top of the stack is coloured

1/12The script starts running at the top level.

The big ideas

What you need to know

A function passed as an argument

You hand a function to another function, and that function decides when to call it.

Sync callbacks

map, filter and forEach call your callback right away, once per item, before moving on.

Async callbacks

setTimeout and event listeners call your function later, after something happens.

Callback hell

Nesting callback inside callback makes a sideways pyramid that's hard to read. Promises and async/await fix this.

See it in code

Walk through the code

js
1function fetchMarks(roll, callback) {2  setTimeout(() => {3    if (!roll) return callback(new Error("No roll number"));4    callback(null, { roll, marks: 87 });5  }, 500);6}7 8fetchMarks(42, (err, result) => {9  if (err) return console.log(err.message);10  console.log(result.marks);   // 87, after half a second11});12 13[1, 2, 3].forEach((n) => console.log(n * 10)); // sync: 10, 20, 30

1/4fetchMarks takes a callback. With no roll, it passes an Error and stops.

The (err, result) shape is called error-first. Node.js used it everywhere: check err first, and only use result if err is null.

Save yourself the pain

Common mistakes

Oops

Calling the callback twice by forgetting to return after the error case.

Do this instead

Write return callback(err) so the function stops there and the success line never runs.

Oops

Nesting five callbacks deep to do five steps in order.

Do this instead

Wrap the steps in promises and use async/await. The code reads top to bottom again.

Your mission

Write your own forEach

~15 min

Quick check

What's the order? setTimeout(() => console.log("A"), 0); console.log("B");

Go deeper

  1. 1Write a function that accepts a callback and calls it after a `setTimeout`. Validate your understanding by applying it in a small practical example.
  2. 2Recognize 'callback hell' from deeply nested callbacks in older code. Validate your understanding by applying it in a small practical example.
  3. 3Understand why Promises/async-await were introduced to solve callback hell.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge