Try…catch is a JavaScript construct for error handling that allows catching and handling exceptions that occur during code execution. The try block contains code that might cause an error, while the catch block contains code to handle that error. The optional finally block executes regardless of whether an error occurred or not.
Key benefits:
Try…catch is a fundamental error handling construct in JavaScript that allows gracefully handling exceptions and preventing program crashes. This is especially important in asynchronous code and when working with external APIs.
The try…catch construct consists of three parts:
try {
// Code that might cause an error
const result = riskyOperation();
console.log(result);
} catch (error) {
// Error handling
console.error('An error occurred:', error.message);
} finally {
// Optional block that executes in any case
console.log('Resource cleanup');
}Commonly used when parsing JSON data:
function parseUserData(jsonString) {
try {
const userData = JSON.parse(jsonString);
return userData;
} catch (error) {
if (error instanceof SyntaxError) {
console.error('Invalid JSON format:', error.message);
return null;
} else {
throw error; // Re-throw other types of errors
}
}
}
// Usage
const validJson = '{"name": "John", "age": 30}';
const invalidJson = '{"name": "John", "age":}'; // Invalid JSON
console.log(parseUserData(validJson)); // {name: "John", age: 30}
console.log(parseUserData(invalidJson)); // null (with error message)Important when making HTTP requests:
async function fetchUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const userData = await response.json();
return userData;
} catch (error) {
if (error instanceof TypeError) {
console.error('Network error:', error.message);
} else if (error.message.includes('HTTP error')) {
console.error('Server error:', error.message);
} else {
console.error('Unknown error:', error.message);
}
// Return default value
return { id: userId, name: 'User not found' };
}
}Useful when working with browser storage:
function saveToLocalStorage(key, data) {
try {
localStorage.setItem(key, JSON.stringify(data));
console.log('Data saved successfully');
} catch (error) {
if (error instanceof DOMException) {
if (error.name === 'QuotaExceededError') {
console.error('Storage quota exceeded');
} else {
console.error('Storage access error:', error.message);
}
} else {
console.error('Unknown error:', error.message);
}
}
}
function loadFromLocalStorage(key) {
try {
const data = localStorage.getItem(key);
return data ? JSON.parse(data) : null;
} catch (error) {
console.error('Error loading data:', error.message);
return null;
}
}function validateUserInput(input) {
try {
// Check required fields
if (!input.name || !input.email) {
throw new Error('Required fields are missing');
}
// Check email format
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(input.email)) {
throw new Error('Invalid email format');
}
// Check age
if (input.age && (input.age < 0 || input.age > 150)) {
throw new Error('Invalid age');
}
return { isValid: true, data: input };
} catch (error) {
return { isValid: false, error: error.message };
}
}
// Usage
const validInput = { name: 'John', email: 'john@example.com', age: 25 };
const invalidInput = { name: 'John', email: 'invalid-email' };
console.log(validateUserInput(validInput)); // { isValid: true, ... }
console.log(validateUserInput(invalidInput)); // { isValid: false, error: "Invalid email format" }async function processMultipleOperations() {
const operations = [
fetch('/api/data1'),
fetch('/api/data2'),
fetch('/api/data3')
];
try {
// Execute all operations in parallel
const results = await Promise.all(operations.map(op =>
op.catch(error => ({ error }))
));
// Process results
const successful = results.filter(result => !result.error);
const failed = results.filter(result => result.error);
console.log(`Successful: ${successful.length}, Errors: ${failed.length}`);
return { successful, failed };
} catch (error) {
console.error('Critical error:', error.message);
throw error;
}
}// Custom error class
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}
function processFormData(formData) {
try {
// Validation
if (!formData.username) {
throw new ValidationError('Username is required', 'username');
}
if (formData.username.length < 3) {
throw new ValidationError('Username must be at least 3 characters', 'username');
}
if (!formData.password) {
throw new ValidationError('Password is required', 'password');
}
// Process data
return { success: true, data: formData };
} catch (error) {
if (error instanceof ValidationError) {
return {
success: false,
error: error.message,
field: error.field
};
} else {
// Other error types
return {
success: false,
error: 'An unknown error occurred'
};
}
}
}// ❌ Ignoring errors
try {
riskyOperation();
} catch (error) {
// Empty catch block - bad practice
}
// ✅ Proper handling
try {
riskyOperation();
} catch (error) {
console.error('Error:', error.message);
// Or send to logging system
logError(error);
}// ❌ Catching all errors identically
try {
riskyOperation();
} catch (error) {
alert('An error occurred'); // Not informative
}
// ✅ Different handling for different error types
try {
riskyOperation();
} catch (error) {
if (error instanceof TypeError) {
console.error('Type error:', error.message);
} else if (error instanceof ReferenceError) {
console.error('Reference error:', error.message);
} else {
console.error('Other error:', error.message);
}
}// ❌ Forgotten finally for resource cleanup
function processFile(filename) {
let file;
try {
file = openFile(filename);
return processData(file);
} catch (error) {
console.error('Error processing file:', error);
}
// File might remain open!
}
// ✅ Proper finally usage
function processFile(filename) {
let file;
try {
file = openFile(filename);
return processData(file);
} catch (error) {
console.error('Error processing file:', error);
throw error;
} finally {
// Always close file
if (file) {
closeFile(file);
}
}
}| Method | Advantages | Disadvantages |
|---|---|---|
| try…catch | Flexible, clear syntax | Can hide errors |
| Promise.catch() | For asynchronous operations | Chains can be complex |
| window.onerror | Global handling | Only for runtime errors |
| process.on(‘uncaughtException’) | For Node.js | Only for unhandled errors |
Try…catch is an important tool for creating reliable JavaScript applications. Understanding proper usage of this construct helps create more stable and predictable code.
What will be output to the console and why? Fix the code if necessary:
function divide(a, b) {
if (b === 0) {
throw new Error('Division by zero');
}
return a / b;
}
function calculate() {
try {
console.log('1. Start calculation');
const result1 = divide(10, 2);
console.log('2. Result 1:', result1);
const result2 = divide(10, 0);
console.log('3. Result 2:', result2);
const result3 = divide(20, 4);
console.log('4. Result 3:', result3);
} catch (error) {
console.log('5. Error:', error.message);
}
console.log('6. End calculation');
}
calculate();Answer: The following will be output to the console:
1. Start calculation
2. Result 1: 5
5. Error: Division by zero
6. End calculation
Explanation:
console.log('1. Start calculation') executesdivide(10, 2) is called — returns 5, “2. Result 1: 5” is outputdivide(10, 0) is called — throws Error(‘Division by zero’)Fixed version with individual handling of each operation:
function divide(a, b) {
if (b === 0) {
throw new Error('Division by zero');
}
return a / b;
}
function calculate() {
console.log('1. Start calculation');
// Handle each operation separately
try {
const result1 = divide(10, 2);
console.log('2. Result 1:', result1);
} catch (error) {
console.log('Error in operation 1:', error.message);
}
try {
const result2 = divide(10, 0);
console.log('3. Result 2:', result2);
} catch (error) {
console.log('Error in operation 2:', error.message);
}
try {
const result3 = divide(20, 4);
console.log('4. Result 3:', result3);
} catch (error) {
console.log('Error in operation 3:', error.message);
}
console.log('5. End calculation');
}
calculate();This will output:
1. Start calculation
2. Result 1: 5
Error in operation 2: Division by zero
4. Result 3: 5
5. End calculation
It’s important to understand that when an exception occurs in a try block, execution immediately jumps to the catch block, and the rest of the code in the try block doesn’t execute.
Want more articles to prepare for interviews? Subscribe to EasyAdvice, bookmark the site and improve yourself every day 💪