Error Handling in Async/Await in JavaScript
try/catch with await is the cleanest error handling. Here is how it works and edge cases.
Error Handling in Async/Await in JavaScript
try/catch with await is the cleanest way to handle errors in async code. Here is how it works and edge cases.
Basic try/catch
async function main() { try { const data = await fetchP("/api"); const result = await processP(data); render(result); } catch (err) { console.error("Error:", err); } } `` If any `await` rejects, the `catch` block runs with the rejection reason. ### try/catch Catches Throws Too ```js async function main() { try { const data = await fetchP("/api"); if (!data.ok) throw new Error("bad data"); // caught by catch render(data); } catch (err) { console.error(err); } } `` ### Catching Specific Errors ```js async function main() { try { const data = await fetchP("/api"); render(data); } catch (err) { if (err instanceof TypeError) { console.error("Network error:", err); } else if (err instanceof CustomError) { console.error("Custom error:", err); } else { console.error("Unknown error:", err); } } } `` ### Recovering and Continuing ```js async function main() { let data; try { data = await fetchP("/api"); } catch (err) { console.error("Using fallback:", err); data = fallbackData; // recover } render(data); // continues with fallback } `` ### Re-throwing ```js async function main() { try { const data = await fetchP("/api"); return process(data); } catch (err) { console.error(err); throw err; // re-throw to propagate to caller } } `` ### Handling Errors per await ```js async function main() { // each await with its own try/catch let user; try { user = await fetchUserP(id); } catch (err) { user = null; } let posts; try { posts = await fetchPostsP(user); } catch (err) { posts = []; } render(user, posts); } `` This is more granular but verbose. Use when different operations need different error handling. ### The Takeaway `try/catch` with `await` is the cleanest error handling for async code. It catches rejections and thrown errors. Recover by assigning a fallback in the `catch` block. Re-throw to propagate. Use per-`await` `try/catch` for granular handling. Always handle errors to avoid unhandled rejections.
Use try/catch around the await calls. If any await rejects, the catch block runs with the rejection reason. try/catch also catches thrown errors inside the try block.
Yes. try/catch catches both promise rejections (from await) and thrown errors (from throw statements inside the try block). This is one advantage over .catch, which only catches promise rejections.
Assign a fallback value in the catch block, then continue. For example: try { data = await fetch(); } catch { data = fallback; } render(data); // continues with fallback.
Use throw err in the catch block. This propagates the error to the caller. The caller can catch it with their own try/catch or let it propagate further.
Use separate try/catch blocks for each await: try { user = await fetchUser(); } catch { user = null; } try { posts = await fetchPosts(); } catch { posts = []; }. This gives granular control but is more verbose.
Ready to master React completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master React
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

