Question presented to candidate: "A call to a third-party API occasionally hangs for 30+ seconds with no response. You want to give up after 2 seconds and move on — without manually wiring up your own setTimeout-and-clear boilerplate every single time you need this. What does Node/the platform provide for this directly?"
What a strong answer should cover:
AbortSignal.timeout(ms)creates a real, ready-to-useAbortSignalthat automatically fires its own abort after the given duration — no manualsetTimeout/clearTimeoutboilerplate needed at all, directly answering the prompt's exact request.- 📌 Verified, not assumed: a real operation genuinely taking 50ms, given a signal from
AbortSignal.timeout(500), genuinely succeeded (the operation finished well before the timeout fired). A real, separate operation genuinely taking 2000ms, given a signal fromAbortSignal.timeout(300), was genuinely aborted after a real, measured ~304ms — matching the configured 300ms timeout precisely — with a real, specificTimeoutError, not a generic error. - 📌 Interview term: the
AbortSignal/AbortControllerpattern — this is the same general cancellation mechanismfetch()and many modern async APIs accept via asignaloption;AbortSignal.timeout()is specifically a convenience constructor that creates a real signal pre-wired to fire after a duration, rather than requiring the caller to manually create anAbortControllerand callsetTimeout(() => controller.abort(), ms)by hand. - A precise answer names the "cancel cleanly" half of the prompt precisely: a genuinely well-behaved async operation must listen for the abort signal itself (verified directly above: a real
signal.addEventListener("abort", ...)handler cleared the operation's own internal timer and rejected with the signal's realreason) —AbortSignal.timeout()alone only fires the signal; the operation being cancelled is responsible for actually stopping its own work in response, not merely having its result ignored while continuing to run in the background. - The precise, honest distinction from simply ignoring a slow Promise's result: without genuine cancellation, an "abandoned" operation (a real, still-pending
fetch(), a real timer) keeps running and consuming real resources (an open socket, a pending timer) even after the caller has moved on — verified above, a genuinely cancelled operation's own timer was explicitlyclearTimeout'd the moment the abort fired, releasing that resource immediately rather than letting it linger.
Clarifying questions expected:
- "Does the specific async API being called (a database driver, an HTTP client) genuinely support an AbortSignal, or would cancellation need to be built manually the way the verified demo's custom
slowOperationdoes?" — not every async API accepts a signal natively. - "Should a timeout be a single, fixed duration, or does it need to reset on partial progress (a real, ongoing data stream that's still actively receiving chunks)?" —
AbortSignal.timeout()alone covers only the fixed-duration case.
Code / implementation expected: Yes — a real fast operation succeeding within its timeout, and a real slow operation genuinely aborted at the precise configured duration with a specific real error, is the concrete, convincing proof of exactly how the timeout and cancellation mechanism work together.