一、错误处理的核心机制
Express通过四参数中间件构建错误处理流水线,需特别注意:
javascript
// 错误中间件标准结构
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({error: err.message || '服务器内部错误' });
});
• 执行顺序原则 :必须定义在所有常规中间件和路由之后
• 错误传递机制 :通过next(err)
触发错误处理链
• 响应灵活性:支持HTML、JSON、纯文本等多种响应格式
开发陷阱 :忘记调用
next(err)
会导致错误未被捕获,引发进程崩溃
二、同步与异步错误的差异化处理
-
同步错误自动捕获
javascriptapp.get('/sync', (req, res) => { throw new Error('同步错误示例'); // Express自动捕获 });
-
异步错误必须显式传递
javascript// Promise方案 app.get('/async', async (req, res, next) => { Promise.reject(new Error('异步错误示例')) .catch(next); // Correctly pass 'next' without calling it immediately,必须手动调用next方法 }); // Callback方案 app.get('/callback', (req, res, next) => { fs.readFile('missing.txt', (err, data) => { if (err) return next(err); // 错误传递关键 res.send(data); }); });
三、错误处理架构设计(防御体系)
-
日志记录层
javascriptfunction logErrors(err, req, res, next) { console.error(`${Date.now()}|${req.ip}|${err.stack}`); next(err); // 传递给下一层 }
-
客户端错误层
javascriptfunction clientErrorHandler(err, req, res, next) { if (req.xhr) { res.status(500).json({code: 'API_ERR'}); // AJAX请求专用响应 } else { next(err); } }
-
终极兜底层
javascriptapp.use((err, req, res, next) => { if (res.headersSent) { return next(err); // 交还Express默认处理 } res.status(500).send('系统开小差了,工程师正在抢修!'); });
-
未匹配路由处理
javascriptapp.use('*', (req, res) => { res.status(404).sendFile('./public/404.html'); // 统一404页面 });