Node.js 文件系统异步异常捕获应优先使用 fs/promises + async/await,错误可被 try/catch 直接捕获;次选 Promise 链 + .catch() 统一处理;避免回调模式中漏判 err 导致静默失败,并辅以 unhandledrejection 兜底和 err.code 日志记录。

在 Node.js 文件系统操作中捕获异步异常,核心是避免回调地狱、统一错误出口,并利用现代 JavaScript 的错误处理机制。同步方法可用 try/catch,但异步操作必须依赖 Promise 链或 async/await + try/catch,否则错误会静默丢失。
用 fs/promises + async/await 捕获最干净
这是当前官方推荐方式,代码接近同步,错误可被 try/catch 直接捕获:
- 导入
fs.promises(Node.js v10+ 内置),不用手动包装 Promise -
await每个操作,任何失败都会抛出 Error,进入catch块 - 错误堆栈完整,包含具体文件路径和行号,便于定位
示例:
const fs = require('fs').promises;async function safeReadFile(path) {
try {
const data = await fs.readFile(path, 'utf8');
return JSON.parse(data);
} catch (err) {
if (err.code === 'ENOENT') {
console.error(`文件不存在: ${path}`);
} else if (err.code === 'EACCES') {
console.error(`权限不足: ${path}`);
} else {
console.error('解析失败:', err.message);
}
}
}
用 Promise 链 + .catch() 统一收口
适合不使用 async/await 的场景,或需链式组合多个 fs 操作:
立即学习“Java免费学习笔记(深入)”;
- 每个 fs 方法返回 Promise,用
.then()串联逻辑 - 所有步骤的异常都会被末尾的
.catch()捕获,无需层层检查err - 注意:不能在
.then()回调里用throw后再写另一个.then(),否则可能跳过后续处理
示例:
fs.readFile('config.json', 'utf8').then(data => JSON.parse(data))
.then(config => fs.writeFile('backup.json', JSON.stringify(config)))
.catch(err => {
console.error('文件读取、解析或写入失败:', err.message);
// 可在此统一上报或降级处理
});
别踩坑:回调模式下错误容易漏掉
传统 fs.readFile(path, callback) 方式仍存在,但错误处理极易出错:
- 必须严格遵守“错误优先”约定:
(err, data) => { if (err) return handleError(err); ... } - 漏写
if (err)或忘记return,会导致data为undefined时继续执行,引发后续TypeError - 嵌套多层回调时,错误无法跨层级传递,只能逐层判断
不推荐写法(风险高):
fs.readFile('a.txt', (err, a) => {if (err) console.error(err); // 忘记 return → 下面代码仍会执行
fs.readFile('b.txt', (err, b) => {
console.log(a.length + b.length); // a 或 b 可能是 undefined
});
});
补充:全局兜底与日志记录
即使主流程做了捕获,也建议加一层防御:
- 监听
unhandledrejection,捕获未被.catch()或try/catch处理的 Promise 拒绝 - 对关键操作(如写配置、删临时文件)加
finally块做清理,比如关闭流、释放锁 - 记录
err.code(如ENOSPC、EMFILE)比只记err.message更利于运维排查


















