Node.js 错误处理基础
错误处理是 Node.js 应用稳定性的保障。
错误类型
Error 类别
| 类型 | 说明 | 示例 |
|---|---|---|
| 同步错误 | 执行时立即抛出 | throw new Error() |
| 异步错误 | 回调/Promise 中发生 | callback(err) |
| 系统错误 | 系统/网络操作失败 | 文件不存在、网络超时 |
| 用户错误 | 输入验证失败 | 参数校验失败 |
内置错误类型
JavaScript
// 常见内置错误
new Error('通用错误');
new TypeError('类型错误');
new RangeError('范围错误');
new ReferenceError('引用错误');
new SyntaxError('语法错误');
new URIError('URI错误');
错误属性
JavaScript
const err = new Error('发生错误');
console.log(err.message); // 错误消息
console.log(err.name); // 错误名称
console.log(err.stack); // 堆栈追踪
// 创建时附加信息
const err = new Error('查询失败');
err.code = 'QUERY_ERROR';
err.status = 500;
err.details = { query: 'SELECT *' };
错误传播
同步传播
JavaScript
function divide(a, b) {
if (b === 0) {
throw new Error('除数不能为零');
}
return a / b;
}
// 调用处捕获
try {
const result = divide(10, 0);
} catch (err) {
console.error('捕获:', err.message);
}
异步传播
JavaScript
// 回调风格
function readFile(path, callback) {
fs.readFile(path, (err, data) => {
if (err) return callback(err);
callback(null, data);
});
}
// 调用处处理
readFile('file.txt', (err, data) => {
if (err) {
console.error('读取失败:', err);
return;
}
console.log(data);
});
错误处理原则
不要吞掉错误
JavaScript
// 错误做法
try {
someOperation();
} catch (err) {
// 吞掉错误,无任何处理
}
// 正确做法
try {
someOperation();
} catch (err) {
console.error(err);
// 记录日志、通知用户、恢复状态
}
错误优先回调
JavaScript
// Node.js 回调约定:第一个参数为错误
function asyncOperation(callback) {
try {
const result = doSomething();
callback(null, result); // 成功:null 作为 err
} catch (err) {
callback(err); // 失败:err 作为第一个参数
}
}
区分错误类型
JavaScript
// 可预期的用户错误 vs 系统错误
function validateInput(input) {
if (!input) {
// 用户错误,可预期
throw new ValidationError('输入不能为空');
}
}
function connectDB() {
// 系统错误,不可预期
throw new DatabaseError('数据库连接失败');
}
错误处理策略
| 错误类型 | 处理策略 |
|---|---|
| 用户输入错误 | 返回友好提示,不记录日志 |
| 业务逻辑错误 | 记录日志,返回错误响应 |
| 系统错误 | 记录详细日志,通知管理员 |
| 未知错误 | 记录堆栈,分析后处理 |
最佳实践
JavaScript
// 统一错误处理
class AppError extends Error {
constructor(message, statusCode, code) {
super(message);
this.statusCode = statusCode;
this.code = code;
this.isOperational = true; // 可操作的错误
}
}
// 区分可恢复和不可恢复错误
function handleError(err) {
if (err.isOperational) {
// 可恢复:记录并继续
logger.warn(err.message);
} else {
// 不可恢复:记录并退出
logger.error(err.stack);
process.exit(1);
}
}
注意事项
- 错误优先回调是 Node.js 约定
- 区分用户错误和系统错误
- 记录错误时包含堆栈信息
- 生产环境不暴露内部错误给用户
要点总结
- 区分同步错误和异步错误
- 使用内置错误类型或自定义错误
- 错误优先回调约定:
(err, result) - 不吞掉错误,必须处理或记录
- 区分可恢复和不可恢复错误
📝 发现内容有误?点击此处直接编辑