Error Handling in Node.js
Overview
Proper error handling is crucial for maintaining a robust and user-friendly application. In Node.js, errors can occur during asynchronous operations, API calls, or when interacting with databases. This guide covers best practices for error handling in Node.js applications.
Using Try-Catch Blocks
For synchronous code, you can use try-catch blocks to handle errors:
try {
// Code that may throw an error
const result = riskyFunction();
} catch (error) {
console.error('Error occurred:', error);
// Handle the error (e.g., send a response to the client)
}
Handling Errors in Async Functions
For asynchronous functions, you can use try-catch along with async/await:
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Fetch error:', error);
}
}
Centralized Error Handling Middleware
In Express, you can create centralized error handling middleware to handle errors consistently:
// Error handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ message: 'Something went wrong!' });
});
Throwing Custom Errors
You can create custom error classes to handle specific error scenarios:
class CustomError extends Error {
constructor(message, status) {
super(message);
this.status = status;
}
}
// Usage
throw new CustomError('Invalid input', 400);
Logging Errors
It’s essential to log errors for debugging and monitoring purposes. You can use libraries like winston
or morgan
:
npm install winston
A simple logging setup might look like this:
const winston = require('winston');
const logger = winston.createLogger({
level: 'error',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log' }),
],
});
// Logging an error
logger.error('Error message');
Best Practices
Follow these best practices for effective error handling:
- Always handle errors gracefully and provide informative responses to users.
- Use centralized error handling to keep your code clean.
- Log errors for later analysis and debugging.
- Test your error handling to ensure it works as expected.