Errors in async functions
1. The basic principle
Errors inside
asyncfunctions automatically turn into a rejected promise (Promise.reject).So you handle them either with:
- a
try...catchblock,- or the
.catch()method on the returned promise.
2. Example with try...catch (the main approach)
async function getData() {
try {
const res = await fetch("https://no-such-domain.com");
const data = await res.json();
console.log(data);
} catch (error) {
console.error("An error occurred:", error.message);
}
}
getData();Output:
An error occurred: fetch failedHere try...catch works just like it does in synchronous code,
but it catches errors from every await inside it.
3. Why this works
await "pauses" the function until the promise settles.
If the promise is rejected, await throws an exception,
and control passes to catch.
Example:
async function example() {
const result = await Promise.reject("Error!");
console.log(result); // never runs
}
example().catch(console.error);Output:
Error!4. An error without try...catch: the promise gets rejected
If you don't wrap await in try...catch,
the function simply returns a rejected promise,
which you can handle with .catch():
async function fail() {
throw new Error("Something went wrong");
}
fail().catch(err => console.error("Caught:", err.message));Output:
Caught: Something went wrongThis is equivalent to handling .catch() on regular promises.
5. Several awaits, one try zone
You can wrap several awaits in a single try
if you want to handle all the errors the same way:
async function loadUserData() {
try {
const user = await fetch("/api/user");
const posts = await fetch("/api/posts");
const comments = await fetch("/api/comments");
} catch (e) {
console.error("Error loading data:", e);
}
}If any of the operations fails, control immediately jumps to catch.
6. A local try for fine-grained control
Sometimes it's better to wrap individual awaits if you want to handle errors differently for each:
async function example() {
try {
const user = await fetchUser();
} catch (e) {
console.error("Error loading the user:", e);
}
try {
const posts = await fetchPosts();
} catch (e) {
console.error("Error loading posts:", e);
}
}7. Example: "healing" an error (like .catch().then())
If you return a value from catch, the function continues running:
async function example() {
try {
await Promise.reject("Error!");
} catch (e) {
console.log("Caught:", e);
return "Default value";
}
}
example().then(result => console.log("Result:", result));Output:
Caught: Error!
Result: Default value8. Errors in parallel awaits (Promise.all)
If you run several awaits in parallel through Promise.all,
and at least one of the promises rejects, the whole Promise.all fails.
async function parallel() {
try {
const [a, b] = await Promise.all([
Promise.resolve("ok"),
Promise.reject("error"),
]);
} catch (e) {
console.log("Caught:", e);
}
}
parallel();Output:
Caught: error9. Using catch directly (an alternative to try...catch)
async function getUser() {
const res = await fetch("/api/user").catch(err => {
console.error("Error during the request:", err);
return null; // return a safe fallback value
});
console.log("Result:", res);
}
getUser();This approach is often used when you just need to "suppress" an error and let the program continue.
10. Best practices
| Situation | What to use |
|---|---|
| Handling errors inside one function | try...catch |
| Handling errors when calling an async function | .catch() |
| Different error types with different reactions | Several try...catch blocks |
Several parallel awaits | Promise.allSettled() instead of Promise.all |
| Logging and rethrowing | catch (e) { log(e); throw e; } |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.