Quiz

How do you handle errors in asynchronous operations?

Topics
AsyncJavaScript

TL;DR

Handle promise rejections with try...catch around await or with .catch() on a promise chain. Remember that Fetch fulfills its promise for HTTP errors such as 404 and 500, so check response.ok and throw an application error yourself.

async function fetchData() {
try {
// This request will fail (example domain)
const response = await fetch('https://api.example.com/data');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData(); // Error fetching data: ....

With Promises, you can use the .catch() method:

fetch('https://api.example.com/data') // This request will fail (example domain)
.then((response) => {
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
})
.then((data) => console.log(data))
.catch((error) => console.error('Error fetching data:', error));

Match the error channel

Error handling must follow the abstraction that reports completion: promise rejections and callback error arguments travel through different channels.

Asynchronous error channels

A try...catch around code that merely starts callback-based work cannot catch an error thrown later by that callback.

Using try...catch with async/await

Basic usage

When using async/await, you can handle errors by wrapping your asynchronous code in a try...catch block. This allows you to catch any errors that occur during the execution of the await statement.

async function fetchData() {
try {
// This request will fail (example domain)
const response = await fetch('https://api.example.com/data');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData(); // Error fetching data: ....

Nested asynchronous operations

If you have multiple asynchronous operations, you can nest try...catch blocks to handle errors at different levels.

async function fetchUser() {
// Simulate a successful async operation
return { id: 1, name: 'Alice' };
}
async function fetchUserPosts() {
// Simulate a failed async operation
throw new Error('Failed to fetch posts');
}
async function loadUserData() {
try {
const user = await fetchUser();
console.log('User:', user);
try {
const posts = await fetchUserPosts();
console.log('Posts:', posts);
} catch (postsError) {
console.error('Error fetching posts:', postsError.message);
}
} catch (userError) {
console.error('Error fetching user:', userError.message);
}
}
loadUserData();

Using .catch() with Promises

Basic usage

When working with Promises, you can handle errors using the .catch() method. This method is called if the Promise is rejected.

fetch('https://api.example.com/data')
.then((response) => {
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
})
.then((data) => console.log(data))
.catch((error) => console.error('Error fetching data:', error));

Chaining multiple Promises

If you have multiple Promises chained together, you can use a single .catch() at the end to handle any errors that occur in any of the Promises.

fetch('https://api.example.com/data')
.then((response) => {
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
})
.then((data) => {
// Process data
return processData(data);
})
.then((result) => {
// Further processing
console.log(result);
})
.catch((error) => console.error('Error in the chain:', error));

Further reading

Exercises

Check your understanding
Beta
Check your understanding Exercise 1 of 3
Check your understanding Exercise 1 of 3

Assume the server responds normally with HTTP 404. How does the promise returned by load() settle?

async function load() {
try {
const response = await fetch('/missing');
return response.status;
} catch {
return 'caught';
}
}