Synchronous and Asynchronous Order

Explain the order of school-screen messages

A teacher sees messages appear in a different order from their position in the source. To debug this, we need to know which calls complete now and which schedule work for later.

Synchronous execution completes the current operation before moving to the next statement. An asynchronous operation arranges completion for later. Callback syntax alone does not reveal which behavior an API uses.

  1. Trace immediate calls

    Follow a callback invoked inside its receiving function.

  2. Trace queued handlers

    Separate current work, promise handlers and timer callbacks.

  3. Check the API

    Avoid guessing timing from the presence of a callback.

Separate the current sequence from scheduled work

  1. Current sequence

    Run immediate calls and synchronous logs.

    Saved locally → Screen ready
  2. Promise handler

    Run after the current sequence finishes.

    Report ready
  3. Timer callback

    Run when the timer task gets a turn.

    Reminder
Read these stages alongside the complete example. They explain the relationship; they do not execute code.

Follow what the receiving function actually does

saveNow below directly calls its callback in its own body. That callback is synchronous and prints before saveNow returns. Promise.then registers a handler that runs after the current synchronous code.

In this simple browser-like example, the fulfilled promise handler runs before the zero-delay timer callback. Promise reactions use the microtask queue; timers arrange later tasks. A microtask is queued work processed after the current synchronous turn before the next ordinary task.

Before starting, review eventual completion. These examples use JavaScript; other languages can use different syntax and rules.

Trace an immediate callback, a promise and a timer

First saveNow invokes its supplied callback and prints Saved locally. Both later callbacks are then registered. Screen ready prints during the current sequence.

When that sequence finishes, the promise handler prints Report ready. The timer callback later prints Reminder. A zero delay does not mean execute inside setTimeout.

JavaScript · local teaching example

function saveNow(callback) {
  callback();
}
saveNow(() => console.log("Saved locally"));
Promise.resolve().then(() => console.log("Report ready"));
setTimeout(() => console.log("Reminder"), 0);
console.log("Screen ready");

Expected output

Saved locally
Screen ready
Report ready
Reminder

Apply the rule to a small change

Predict the output when an immediate callback is followed by a promise handler and one final log.

Worked answer

A prints during immediate. C prints at the end of the current sequence. B prints afterward in the promise handler, so the result is A, C, B.

JavaScript · local teaching example

function immediate(callback) { callback(); }
immediate(() => console.log("A"));
Promise.resolve().then(() => console.log("B"));
console.log("C");

Expected output

A
C
B

Recognize mistakes and limits

A timer delay is a scheduling threshold, not an exact appointment. Busy execution, other tasks and runtime policies can make its callback run later.

Do not generalize this single-turn example into a full ordering rule for every Node.js API. Runtime-specific phases, I/O and when work is scheduled can change the relationships. Check the relevant API documentation.

Repeatedly adding promise microtasks can delay ordinary tasks. Moving a large calculation into then alone does not make it cheap or responsive.

For the language or tool rules used here, see JavaScript promise chaining and timing.

Check the core idea

JavaScript · code for this question

function saveNow(callback) {
  callback();
}
saveNow(() => console.log("Saved locally"));
Promise.resolve().then(() => console.log("Report ready"));
setTimeout(() => console.log("Reminder"), 0);
console.log("Screen ready");
Is the callback passed to saveNow asynchronous?
Choose one answer. You can try again.

Answer and explanation

No. saveNow calls it directly before returning.

Correct. Its body defines the timing.

Apply the idea to a new situation

What does setTimeout(callback, 0) mean here?
Choose one answer. You can try again.

Answer and explanation

Schedule callback for a later eligible timer task.

Correct. Current synchronous work finishes first.

Predict order from the execution contract

Trace direct calls first, then the scheduled work supported by the runtime. Callback shape alone is insufficient; timer and promise APIs have different scheduling contracts.

Connect this idea with ways to represent completion and tracing intermediate observations.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Callbacks, Promises and Futures →