How to use Try and Catch Statement in JavaScript?
How to Use try and catch in JavaScript (Easy Guide)
In JavaScript, the try...catch statement helps you handle errors without crashing your program. You put risky code inside try. If an error happens, control moves to catch, where you can handle it. You can also use finally to run clean-up code that should execute whether an error happens or not.
Syntax
try {
// Code that might throw an error
} catch (error) {
// Handle the error
// error.name, error.message, error.stack are available
} finally {
// Optional: runs always
}
Basic Example
function safeDivide(a, b) {
try {
if (b === 0) {
throw new Error("Cannot divide by zero");
}
const result = a / b;
console.log("Result:", result);
return result;
} catch (err) {
console.error("Division failed:", err.message);
return null; // Fallback value
} finally {
console.log("Division attempt finished");
}
}
safeDivide(10, 2); // Works
safeDivide(5, 0); // Caught with message
Using throw to Create Your Own Errors
Use throw when you detect invalid input or an unexpected state. This helps you keep your code predictable.
function parseAge(input) {
try {
const age = Number(input);
if (!Number.isInteger(age) || age < 0) {
throw new RangeError("Age must be a non-negative integer");
}
return age;
} catch (err) {
console.warn("Invalid age:", err.message);
return 0; // default age
}
}
parseAge("21"); // 21
parseAge("-3"); // 0 (handled)
Understanding the Error Object
- error.name: Type of error (e.g., Error, TypeError, SyntaxError, RangeError)
- error.message: Human-readable message
- error.stack: Stack trace (useful for debugging)
try {
JSON.parse("{ broken json ");
} catch (err) {
console.log(err.name); // "SyntaxError"
console.log(err.message); // Details about what failed
}
finally: Clean Up Resources
Use finally to stop loaders, close connections, or reset UI states.
let loading = false;
function loadData() {
loading = true;
try {
// simulate work
if (Math.random() < 0.5) throw new Error("Random failure");
console.log("Data loaded");
} catch (err) {
console.error("Load error:", err.message);
} finally {
loading = false; // always reset
console.log("Loader hidden");
}
}
loadData();
Error Handling with async/await
For asynchronous code, wrap await calls in try...catch. Promises without await use .catch().
// Using async/await
async function fetchUser(id) {
try {
const res = await fetch(`https://api.example.com/users/${id}`);
if (!res.ok) throw new Error("Network response was not ok");
const data = await res.json();
return data;
} catch (err) {
console.error("Fetch failed:", err.message);
return null;
}
}
// Using Promises
fetch("https://api.example.com/users")
.then(r => r.json())
.then(data => console.log(data))
.catch(err => console.error("Promise error:", err.message));
Parsing JSON Safely
function safeJSON(str) {
try {
return JSON.parse(str);
} catch (err) {
console.warn("Invalid JSON:", err.message);
return {}; // safe fallback
}
}
safeJSON('{"name":"Ada"}'); // { name: "Ada" }
safeJSON("oops"); // {}
Rethrow Unknown Errors
Handle what you expect, rethrow the rest so higher-level code or logs can catch them.
try {
JSON.parse(userInput);
} catch (err) {
if (err.name === "SyntaxError") {
alert("Please enter valid JSON.");
} else {
throw err; // unexpected: let it propagate
}
}
Common Mistakes to Avoid
- Expecting try...catch to catch async errors without using await or .catch()
- Catching errors but doing nothing (silent failures)
- Using try...catch for normal control flow (keep it for exceptional cases)
- Wrapping huge blocks; keep try blocks small and focused
- Not returning or handling fallback values after catching an error
Best Practices (Quick Checklist)
- Validate inputs early; throw meaningful errors
- Use specific error types (Error, TypeError, RangeError, custom errors)
- Keep try blocks minimal for clarity
- Log errors for debugging; show user-friendly messages in the UI
- Use finally for cleanup (loaders, locks, temporary states)
- Rethrow unknown errors to avoid hiding bugs
Step-by-Step to Add try...catch
- Identify risky code (parsing, network calls, file operations, complex calculations).
- Wrap that code in a try block.
- Handle known failures in catch using error.name and error.message.
- Provide safe defaults or user messages.
- Use finally to clean up UI or resources.
