Glossary / Exception propagation
Exception propagation
Exception propagation is the movement of a thrown value through nested execution until a matching handler catches it or the runtime reports it as uncaught. Synchronous try/catch handles exceptions thrown during its dynamic execution. Promises and async/await create asynchronous propagation paths; callbacks scheduled for later run outside the original call stack.
Synchronous and asynchronous boundaries
try {
setTimeout(() => { throw new Error("later"); }, 0);
} catch (error) {
// Does not catch the timer callback's later throw.
}
async function load() {
try {
return await fetchData();
} catch (error) {
// Handles rejection from fetchData at the await point.
throw new Error("Loading failed", { cause: error });
}
}
A thrown error in a Promise executor rejects that Promise. A rejection propagates through .then chains until handled. await rethrows a rejected Promise’s reason at the await expression, where surrounding try/catch can handle it. Errors thrown inside later timer or event callbacks do not jump back into a completed caller’s try block.
finally is for cleanup and runs during normal or abrupt completion, but a return or throw from finally can override the earlier result/error. Catch only when you can recover, translate, add meaningful context, or safely report. Always observe asynchronous tasks; detached rejected Promises can become unhandled rejections.
Interview questions
- Can try/catch around setTimeout catch its callback error? No; the callback runs later on a separate task.
- How does await expose a rejection? It throws at the await expression.
- Can finally replace a prior error? Yes, a return/throw from finally can override completion.
- What is an unhandled rejection? A rejected Promise that reaches the host without a rejection handler.