Safe Code
Even the best code can fail. The try..catch block lets you catch errors gracefully and prevent the entire script from crashing.
try {
console.log('Start of try block');
lalala; // Error: variable is not defined!
console.log('End of try block (never reached)');
} catch (err) {
console.log('Error caught: ' + err.message);
} finally {
// Runs ALWAYS — success or failure
console.log('I always run — great for cleanup!');
}
The finally Block
Use finally for cleanup that must happen regardless of the outcome:
async function loadData() {
showLoadingSpinner();
try {
const data = await fetch('/api/data').then(r => r.json());
return data;
} catch (err) {
showError(err.message);
} finally {
hideLoadingSpinner(); // ALWAYS hides — even if an error occurred
}
}
Caution
try..catch only works for synchronous code. Errors inside setTimeout callbacks will NOT be caught. For async code, use try..catch with async/await or .catch() on promises.
Tip
Use finally when you need to guarantee something runs (e.g., hiding a loading spinner, closing a database connection) regardless of whether the operation succeeded or failed.