In web development, error handling is a critical aspect that ensures your application can gracefully handle unexpected situations and provide meaningful feedback to users. Express.js, a popular Node.js framework, provides several mechanisms for handling errors, including middleware specifically designed for this purpose.
Error-handling middleware in Express is different from regular middleware because it has four arguments instead of three: err, req, res, and next. This special signature allows the middleware to be recognized as an error handler by Express. When an error occurs anywhere in your application, you can pass it to next() with the error object, and Express will automatically use this error-handling middleware.
Error-handling middleware functions have the following structure:
function errorHandler(err, req, res, next) {
// Handle the error here
}
Here's a breakdown of each argument:
- `err`: The error object that was thrown or passed to `next()`.
- `req`: The request object.
- `res`: The response object.
- `next`: A function to pass control to the next middleware function. If you don't call this, Express will assume the error has been handled and will not proceed with any further error-handling middleware.
Error-handling middleware should be defined after all other app.use() and routes calls. This ensures that it is only invoked when an error occurs in one of the preceding middlewares or routes.
## Examples
### Basic Error-Handling Middleware
Let's create a simple Express application with basic error handling:
```javascript
const express = require('express');
const app = express();
// A route that throws an error
app.get('/', (req, res) => {
throw new Error('Something went wrong!');
});
// Error-handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port \${PORT}`);
});
In this example:
You can also create more specific error-handling middleware for different types of errors:
const express = require('express');
const app = express();
// A route that throws an error
app.get('/', (req, res) => {
throw new Error('Something went wrong!');
});
// Custom error handler for NotFoundError
app.use((err, req, res, next) => {
if (err instanceof NotFoundError) {
return res.status(404).send('Resource not found');
}
next(err);
});
// General error handler
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port \${PORT}`);
});
In this example:
NotFoundError.NotFoundError and sends a 404 response.In this tutorial, we learned how to create and use error-handling middleware in Express.js. In the next section, we will explore logging with Morgan and Winston, which are essential for monitoring and debugging your application.
Stay tuned for more advanced topics on Express.js!