Callbacks
Introduction
A callback is a function you pass to another function so it can be called later or at a specific moment. Callbacks power array methods, event handlers, timers, and the pre-Promise async style of JavaScript.
The key mental shift is inversion of control: you hand behavior to another function, and that function decides when and how often to call it.
Why This Matters
Callbacks are the bridge from simple functions to asynchronous JavaScript. If you can reason about sync callbacks, async callbacks, error-first conventions, and callback hell, promises and async/await become much easier to learn.
Theory
Synchronous callbacks
Array methods such as map, filter, some, and reduce call your callback immediately during the current call stack. The outer method controls iteration; your callback supplies behavior.
Asynchronous callbacks
Timers, I/O, and user events call your callback later, after the current synchronous code finishes. This is why setTimeout(callback, 0) still runs after the current stack and pending microtasks.
Inversion of control
Passing a callback means you give another function control over execution timing. That is powerful, but it also means you must understand whether the callback is called once, many times, synchronously, asynchronously, with errors, or with a particular this.
Error-first callbacks
Node popularized the convention callback(error, result): if error is non-null, handle it; otherwise use result. Even if you use promises today, recognizing this pattern helps when reading older APIs. Deeply nested callbacks make error handling and sequencing hard; fixes include named functions, small helpers, promises, async/await, or breaking work into composable steps.
Visual Diagrams
caller creates callback
|
v
passes callback to scheduler or iterator
|
v
other function decides when to call it
|
v
callback runs with provided argumentsA callback packages behavior and hands control of timing to another function.
Code Examples
Synchronous predicate callback
filter controls the loop; the callback controls which values are kept.
Error-first callback shape
This style is common in older Node APIs and many interview discussions, even though modern code often wraps it in promises.
Playground
Press Run to execute the code and see output here.
Output Prediction
Predict the output #1
1function doLater(callback) {2 setTimeout(function () {3 callback('done');4 }, 0);5}6 7console.log('before');8doLater(function (result) {9 console.log(result);10});11console.log('after');Coding Exercises
Run callback tasks sequentially
HardImplement runTasks(tasks, done). Each task is a function that accepts a callback and eventually calls it with one result. Run tasks in order, collect their results, and call done(results) after the last task finishes. Do not start task i + 1 until task i has called its callback.
Interview Questions
1What is inversion of control in callbacks?
You pass a function to another API and let that API decide when, how often, and with what arguments it will call your function. This is useful for async work and iteration, but it means you must trust the caller's contract. Promises reduce some inversion-of-control problems by representing the eventual result as a value.
Follow-ups
- How do promises improve on callback nesting?
- What is the error-first callback convention?
2Are all callbacks asynchronous?
No. Array.map and Array.filter callbacks are synchronous; they run immediately during the array method call. Timer, I/O, and event callbacks are asynchronous because the host schedules them for later. Always identify which kind you are dealing with before predicting output.
Quiz
1. Which callback is asynchronous?
Summary
- A callback is a function passed to another function to be called later or during an operation.
- Callbacks can be synchronous, such as array callbacks, or asynchronous, such as timers.
- Callbacks involve inversion of control: another function controls invocation timing.
- Error-first callbacks and callback hell are key historical patterns leading toward promises.
Cheat Sheet
Callback: function passed as behavior.
Sync examples: map, filter, reduce, custom iteration.
Async examples: setTimeout, events, I/O.
Error-first: callback(error, result).
Pitfalls: nested callback hell, unclear timing, repeated calls, lost errors.
Fixes: named helpers, promises, async/await, small composable functions.