Module 24: Asynchronous Programming
Handling errors in async code
🏠The everyday picture
A delivery app that shows a spinner forever when the restaurant closes is worse than one that says "Sorry, this restaurant isn't taking orders. Try another." Failure is normal; silence isn't acceptable.
📘What it really is
- With
async/await, catch failures withtry/catch:
async function showProducts() {
try {
const products = await loadProducts();
console.log(products);
} catch (error) {
console.log("Couldn't load products. Please try again.");
console.error(error);
} finally {
console.log("Done loading.");
}
}
- Show people a calm, useful message; log the technical details where developers can see them.
-
Things that commonly fail: no internet, a slow server (set a timeout), the server returning an error, or data in an unexpected shape.
-
Retrying can help with brief network problems: try again after a short wait, a limited number of times. Never retry endlessly.
-
Every
asynccall should have a plan for failure somewhere up the chain. "Unhandled promise rejection" warnings mean someone forgot. -
With AI: AI often writes the success path only. Ask "what happens if this fails?" for every
await.
🖱️Try it
Write unreliableLoad() that waits half a second, then fails half the time:
if (Math.random() < 0.5) throw new Error("Server busy");
Call it inside try/catch with a friendly message. Then write withRetry(task, attempts) that tries up to
attempts times, waiting a second between tries, and gives up with a clear message.
✅Quick check
Where do you put code that should run whether loading succeeded or failed, like hiding a spinner?
Show the answer
In finally.
Why not retry a failed request forever?
Show the answer
If the problem isn't temporary, it never ends, and repeated requests can overload the server further.
