Skip to content

Node.js 错误处理最佳实践

错误类型

类型说明处理方式
同步错误throw 抛出try/catch
异步回调错误(err, result) 首个参数回调内判断 if (err)
Promise 错误reject.catch() / try/catch + await
EventEmitter 错误error 事件必须监听 on('error'),否则崩溃
未捕获异常未处理的错误process.on('uncaughtException')

同步错误

js
function parseJSON(str) {
  try {
    return JSON.parse(str)
  } catch (err) {
    console.error('JSON 解析失败:', err.message)
    return null  // 返回安全默认值
  }
}

回调错误

js
fs.readFile('./config.json', (err, data) => {
  if (err) {
    console.error('读取失败:', err.message)
    return  // 早返回
  }
  // 正常处理 data
})

Promise / async-await

js
// 统一错误处理中间件
async function handler(req, res) {
  try {
    const data = await fetchData()
    res.json(data)
  } catch (err) {
    res.status(500).json({ error: err.message })
  }
}

EventEmitter 错误(重要!)

js
// EventEmitter 不监听 error 会让 Node.js 崩溃!
const emitter = new EventEmitter()

emitter.on('error', (err) => console.error('捕获:', err))  // 必须有这行
emitter.emit('error', new Error('test'))

// Stream 同理
readStream.on('error', (err) => console.error('流错误:', err))

全局兜底

js
// 未捕获同步异常(最后防线,记录后应退出重启)
process.on('uncaughtException', (err) => {
  console.error('未捕获异常:', err)
  process.exit(1)  // 此时进程状态不确定,应重启
})

// 未处理的 Promise 拒绝(Node 未来版本会改为退出进程)
process.on('unhandledRejection', (reason, promise) => {
  console.error('未处理 Promise 拒绝:', reason)
})

自定义错误类

js
class AppError extends Error {
  constructor(message, statusCode = 500) {
    super(message)
    this.statusCode = statusCode
    this.isOperational = true  // 标记为可预料的业务错误
    Error.captureStackTrace(this, this.constructor)
  }
}

// 使用
throw new AppError('用户不存在', 404)

最佳实践速查

原则做法
不吞错误每个 async 函数用 try/catch 或 .catch()
错误分层业务错误 (4xx) vs 系统错误 (5xx)
EventEmitter必须监听 error 事件
全局兜底uncaughtException + unhandledRejection
生产环境用 PM2 自动重启 + 日志持久化
异步函数await 的 Promise 必须在外层有 catch