Compile Ready
Module 8 · Asynchronous JavaScript

Asynchronous Callbacks

Intermediate10m read12m practice22m total
CallbacksInversion of ControlTimersError FirstAsync Patterns

Introduction

A callback is a function passed to another function to be called later. An asynchronous callback is invoked after some future event: a timer fires, data arrives, a user clicks, or an operation completes.

Callbacks are the oldest JavaScript async pattern. They are still everywhere, even when hidden behind promises and async/await.

Why This Matters

Callbacks reveal two interview-critical ideas: not every callback is asynchronous, and passing a callback creates inversion of control. You give another function the power to decide if, when, how often, and with what arguments your function runs.

Theory

Callback does not automatically mean async

[1, 2, 3].map(callback) calls the callback synchronously during the same stack. setTimeout(callback, 0) calls the callback asynchronously as a later task. Always ask: who invokes the callback, and when?

One-shot versus repeated callbacks

Some async callbacks are one-shot, such as a timer or a single completion handler. Others are repeated, such as event listeners or intervals. Repeated callbacks need cleanup, otherwise they can cause leaks or duplicate work.

Error-first convention

Many Node-style APIs use (error, data) callbacks. The first argument is non-null if the operation failed. This convention made errors explicit before promises were standardized, but it also created repetitive branching and nested control flow.

Inversion of control risks

When you hand a callback to another function, you trust that function to call it exactly once, call it asynchronously if promised, preserve arguments, and handle errors. Bugs such as double-calling a callback are common in callback-heavy systems.

Callback scheduling

A callback-based API can still choose different scheduling mechanisms: synchronous invocation, microtask scheduling, or task scheduling. Good APIs document this. In interviews, always trace the specific scheduling primitive in the snippet.

Visual Diagrams

Callback ownership

Your code
  |
  | passes callback
  v
Async API or helper
  |
  | later decides when to call
  v
callback(value)

Callbacks invert control: the callee owns the moment of invocation.

Synchronous callback versus async callback

Synchronous:
  caller -> helper -> callback -> helper returns -> caller continues

Asynchronous:
  caller -> helper schedules work -> helper returns -> caller continues
                                      later task -> callback

The word callback describes a shape, not a scheduling guarantee.

Code Examples

Error-first callback style

This is common in Node-style APIs. The pattern is useful to recognize even if modern code wraps it in promises.

Loading…

Guard against double callbacks

Robust callback APIs often protect consumers from accidental double invocation.

Loading…

Playground

Loading editor…
Console

Press Run to execute the code and see output here.

Output Prediction

Predict the output #1

javascript
1
2function maybeAsync(callback) {
3 callback('sync');
4
5 setTimeout(function () {
6 callback('async');
7 }, 0);
8}
9
10console.log('before');
11
12maybeAsync(function (value) {
13 console.log(value);
14});
15
16console.log('after');

Predict the output #2

javascript
1
2console.log('start');
3
4setTimeout(function () {
5 console.log('callback');
6}, 0);
7
8Promise.resolve().then(function () {
9 console.log('promise');
10});
11
12console.log('end');

Coding Exercises

Create a once-only async callback

Medium

Implement onceAsync(callback) so the returned function can be called many times, but schedules the original callback at most once. The original callback should run asynchronously with the first value.

Interview Questions

1Does passing a callback make code asynchronous?

No. A callback is just a function argument. It is asynchronous only if the receiving API invokes it later, such as from a timer, event, or I/O completion. Array methods like map call callbacks synchronously.

Asked at:AmazonMicrosoft
2What is inversion of control in callback-based code?

You hand control of your continuation to another function. That function decides when to invoke it, whether to invoke it once or multiple times, what arguments to pass, and how errors are represented. Promises reduce some of this risk by standardizing one settlement and chainable error propagation.

Follow-ups

  • How do promises prevent double completion?
  • Why are repeated event callbacks different from completion callbacks?

Quiz

1. Which callback is synchronous?

2. What is a common risk of callback-based APIs?

Summary

  • A callback is a function passed to be invoked by another function.
  • Callbacks can be synchronous or asynchronous depending on the API.
  • Async callbacks often run as future tasks, but callback style alone does not determine the queue.
  • Callback-heavy code suffers from inversion of control and repetitive error handling.

Cheat Sheet

Callback: function passed to another function.

Not always async: map is sync; setTimeout is async.

One-shot: completion handlers, timers.

Repeated: events, intervals.

Risk: inversion of control, double calls, missing errors, hard nesting.