Overview

1 When a hello isn’t hello

JavaScript feels friendly and immediate, but that simplicity masks a great deal of machinery beneath the surface. This chapter opens by contrasting the language we write with the engines that execute it and the host runtimes that schedule it, showing how observable behavior emerges from their interaction. The aim is to build a deeper, practical understanding of how code actually runs so you can reason about correctness and performance across environments.

A small “hello” puzzle illustrates the core lesson: identical code can produce different outputs depending on runtime and even on module format. Subtle differences in event loops and task queues—such as microtasks, next ticks, timers, and immediates—and the order in which each runtime drains them explain why Node.js in CommonJS mode behaves differently from Node.js in ECMAScript module mode, and why Deno and Bun diverge as well. The takeaway is to avoid relying on precise timing and ordering of asynchronous operations, because those details are host-defined and can vary widely.

The chapter then separates concerns between language-defined behavior (for example, promises), engine implementation details, and host-defined features (such as process.nextTick). It explains scheduling and single-threaded execution via event loops, noting how browsers prioritize UI responsiveness while server runtimes prioritize I/O throughput. With Node.js as the baseline, the book positions itself as an owner’s manual that will progressively demystify types, promises, streams, cryptography, and modules by examining how engines and runtimes cooperate—and sometimes differ—to run your JavaScript.

An illustration of the phases of the Node.js Event Loop from the project documentation (https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick). At the start of each iteration Node.js will first execute timers, then move on to calling pending callbacks, preparing for I/O, polling the operating system for I/O, then performing various checks and cleanup operations before starting over again at the top with timers.

Summary

  • Identical JavaScript code can yield different results in Node.js, Deno, and Bun due to differences in runtime implementation choices
  • The event loop controls execution order, with each runtime implementing different scheduling priorities
  • Language specifications define what must be consistent; implementations and hosts define what can vary
  • Understanding the distinction between language, implementation, and host behaviors prevents unexpected bugs

FAQ

Why does the same “Hello” code print different outputs across Node.js, Deno, Bun, and even between CommonJS and ESM?Because each host runtime (and even each module loader within a runtime) schedules asynchronous work differently. Microtasks, nextTicks, timers, and immediates are drained in different orders across environments, so identical source can produce different print orders.
What are microtasks, nextTicks, and immediates, and how do they differ?Microtasks are language-level tasks (e.g., Promise continuations and queueMicrotask) that the host drains at points it chooses. process.nextTick is a Node.js-only queue that Node drains before microtasks. setImmediate schedules callbacks for a later “check” phase in Node’s event loop. Their relative drain order is host-defined, not guaranteed by the language.
What is the event loop and why is JavaScript often called single-threaded?The event loop repeatedly picks the next unit of work and runs it to completion before moving on. While a task runs, no other JavaScript runs on that thread. Asynchrony comes from scheduling future tasks rather than running code in parallel.
Why do Node.js CommonJS and ESM run the same file with different observable ordering?They use different bootstrapping and evaluation pipelines. The timing of when Node drains nextTick and microtasks around module loading differs between CJS and ESM, so top-level scheduling in the same file can resolve in a different order.
Do browsers support process.nextTick?No. Browsers do not have process.nextTick. They do have microtasks (Promises/queueMicrotask) and macrotask queues (timers, I/O, UI tasks), but the exact queues and their ordering differ from Node.js.
Why is setImmediate not available by default in Deno?setImmediate is a Node-specific API. Deno focuses on web-standard APIs; you can opt into Node compatibility (e.g., import setImmediate from node:timers or enable a compatibility flag) but it is not a global by default.
What’s the difference between language-defined, implementation-defined, and host-defined behavior?Language-defined: specified by ECMAScript and must behave the same everywhere (e.g., Promises’ semantics). Implementation-defined: differences tied to a given engine (e.g., V8 vs SpiderMonkey optimizations). Host-defined: behavior provided by the runtime (e.g., process.nextTick, setImmediate, event loop phases) and can vary widely.
If Node.js and Deno both use V8, why do results still differ?The engine parses and executes JavaScript, but the host runtime controls scheduling, I/O, available globals, and when queues are drained. Different host policies produce different observable ordering even with the same engine.
Should I rely on the exact timing/order of asynchronous tasks?Avoid it whenever possible. Precise ordering can change across runtimes, versions, and module systems. Prefer explicit sequencing (e.g., await, Promise chaining) and write code that does not depend on host-specific drain orders.
Are microtasks tied to a single event loop turn?Not strictly. The host decides when to drain the microtask queue and may do so multiple times within one loop iteration or at different checkpoints, which is why behavior can vary across environments.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$399.99
only $33.33 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • JavaScript in Depth ebook for free
choose your plan

team

monthly
annual
$49.99
$399.99
only $33.33 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • JavaScript in Depth ebook for free