ExpressJS - 错误处理
Express.js - 现代错误处理
Section titled “Express.js - 现代错误处理”健壮的错误处理是任何生产应用程序的关键组成部分。它能防止服务器崩溃,有助于调试,并向用户提供有意义的反馈,同时不暴露敏感的实现细节。
错误处理中间件
Section titled “错误处理中间件”在 Express 中,错误处理通过一种特殊类型的中间件来完成。这个中间件函数有四个参数,而不是通常的三个:(err, req, res, next)。Express 就是通过这种签名来识别它是一个错误处理中间件的。
这个中间件应该在所有其他 app.use() 和路由调用之后最后定义。
app.use((err, req, res, next) => { console.error(err.stack); res.status(500).send('出错了!');});触发错误处理器
Section titled “触发错误处理器”你可以通过两种方式触发错误处理中间件:
**同步错误:**如果在路由处理程序或中间件中的同步代码中抛出错误,Express 将自动捕获它并将其传递给错误处理器。**异步错误:**对于异步代码中的错误(如数据库查询或 API 调用),你必须捕获它们并将其传递给next()。
示例:使用 next() 传递错误
Section titled “示例:使用 next() 传递错误”在此示例中,我们手动创建一个错误并将其传递给 next(err)。这会跳过所有后续的非错误处理中间件和路由,直接跳转到我们的错误处理器。
import express from 'express';
const app = express();
app.get('/problem', (req, res, next) => { // 模拟一个错误 const err = new Error('这是一个模拟错误。'); err.status = 418; // 你可以添加自定义属性
// 将错误传递给下一个中间件 next(err);});
// 在此处定义其他路由和中间件...app.get('/', (req, res) => res.send('欢迎!'));
// 集中式错误处理器(必须是最后一个)app.use((err, req, res, next) => { console.error('发生错误:', err.message);
// 如果未提供状态码,则设置默认值 const statusCode = err.status || 500;
res.status(statusCode).json({ error: { message: err.message || '发生了内部服务器错误。' } });});
app.listen(3000, () => console.log('服务器正在端口 3000 上运行'));当你访问 http://localhost:3000/problem 时,浏览器将显示一个带有 418 状态码的 JSON 响应:
{ "error": { "message": "这是一个模拟错误。" }}处理异步错误
Section titled “处理异步错误”在 async/await 函数中处理错误需要一个 try...catch 块来将错误传递给 next()。
import { findUserById } from './db'; // 假设这是一个异步数据库函数
app.get('/users/:id', async (req, res, next) => { try { const user = await findUserById(req.params.id); if (!user) { // 为“未找到”创建一个特定错误 const err = new Error('未找到用户'); err.status = 404; return next(err); } res.json(user); } catch (error) { // 捕获数据库错误或其他异常 next(error); }});现代开发提示: 像 express-async-errors 这样的库可以自动为你处理这些。只需导入该库,你就可以在异步路由处理程序中消除对 try...catch 块的需求。
错误处理的最佳实践
Section titled “错误处理的最佳实践”**集中化错误处理:**使用一个单一的、集中式的错误处理中间件,以实现一致的错误响应。**不要泄露实现细节:**在生产环境中,切勿将完整的错误堆栈跟踪发送给客户端。记录它用于调试,但发送一个通用、用户友好的消息。**创建自定义错误类:**为了更结构化的错误处理,扩展内置的Error类来创建自定义错误类型(例如ApiError、NotFoundError),这些错误类型可以包含状态码和其他元数据。**处理未捕获的异常:**为了最终的稳定性,监听process.on('uncaughtException')和process.on('unhandledRejection')来捕获 Express 请求-响应周期之外的错误。记录错误并优雅地关闭服务器。