How does try/catch/finally work in JavaScript?
try runs code that might throw; catch handles the error; finally always runs regardless of outcome useful for cleanup.
JavaScript
Overview
`try/catch` is how JavaScript handles runtime errors synchronously. For async code with `async/await`, it works exactly the same way. The `finally` block runs whether or not an error occurred perfect for cleanup logic.
Key Points
- •`try` wraps the code that might throw an error.
- •`catch(error)` runs only if an error was thrown; `error` is the Error object (or whatever was thrown).
- •`finally` always runs even if there's a `return` inside `try` or `catch`.
- •You can throw any value: `throw new Error("msg")`, `throw 42`, `throw { code: 404 }` but Error objects are best practice.
- •Use `error.message`, `error.name`, and `error.stack` for debugging. Custom error classes extend `Error`.
Examples
Basic try/catch
javascripttry {
const data = JSON.parse(invalidJson);
} catch (error) {
console.error('Parse failed:', error.message);
}finally for cleanup (e.g. loading state)
javascriptasync function fetchData() {
setLoading(true);
try {
const data = await api.get('/users');
setUsers(data);
} catch (error) {
setError(error.message);
} finally {
setLoading(false); // always runs, even if catch returns early
}
}Throwing and catching custom errors
javascriptclass ValidationError extends Error {
constructor(field, message) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}
try {
if (!email.includes('@')) throw new ValidationError('email', 'Invalid email');
} catch (error) {
if (error instanceof ValidationError) {
showFieldError(error.field, error.message);
} else {
throw error; // re-throw unexpected errors
}
}Pro Tip
Don't catch errors you can't handle. Catching and swallowing an error (`catch {}`) hides bugs. Either handle it meaningfully or re-throw it. A caught error is not a fixed error.