async/await 依赖 promise rejection 和 try/catch 实现错误捕获;必须用 promise 化的 i/o api(如 fs.promises 或 util.promisify),避免回调中 throw;推荐 try/catch 包裹 await,配合 promise.allsettled 处理并行操作,并监听 unhandledrejection 作全局兜底。

async/await 本身不直接捕获 Node.js 异步 I/O 错误,它依赖 Promise 的状态传递和 try/catch 的同步语义来实现错误捕获。关键在于:只有被 await 的 Promise 被 reject,才会触发 catch;而底层 I/O 错误(如文件不存在、网络超时)必须正确转化为 Promise rejection,才能被 await 捕获。
✅ 正确捕获异步 I/O 错误的前提
Node.js 原生回调 API(如 fs.readFile, http.request)默认不返回 Promise,需手动包装或使用 util.promisify:
const fs = require('fs').promises; // ✅ 直接使用 Promise 版本
// 或
const { promisify } = require('util');
const readFile = promisify(fs.readFile);
如果仍用回调风格却包裹在 async 函数里,外围 try/catch 无法捕获回调中抛出的错误:
// ❌ 错误示范:错误不会被捕获
async function badExample() {
try {
fs.readFile('missing.txt', (err, data) => {
if (err) throw err; // 这个 throw 发生在回调里,已脱离 try/catch 作用域
});
} catch (e) {
console.log('这里永远收不到错误');
}
}
✅ 标准错误捕获模式(推荐写法)
用 try/catch 包裹 await 表达式,所有被 await 的 Promise rejection 都会同步“抛出”到 catch 中:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
async function getUserProfile(userId) {
try {
const user = await db.query('SELECT * FROM users WHERE id = ?', [userId]);
if (!user) throw new Error('User not found');
const avatar = await fs.readFile(`./avatars/${userId}.jpg`);
return { ...user, avatar: avatar.toString('base64') };
} catch (err) {
// 所有错误(DB 查询失败、文件读取失败、业务逻辑 throw)都在这里统一处理
console.error('Failed to load profile:', err.message);
throw err; // 或返回默认值、记录日志、转换为 HTTP 错误等
}
}
✅ 并行 I/O 操作的错误处理策略
Promise.all 遇错即停,适合“全成功才继续”的场景;Promise.allSettled 更稳健,适合容错型批量操作:
// ⚠️ Promise.all:任一失败,整个 reject
try {
const [users, posts, comments] = await Promise.all([
api.getUsers(),
api.getPosts(),
api.getComments()
]);
} catch (err) {
// 只要知道“有失败”,但不知道哪个失败
}
// ✅ Promise.allSettled:始终返回结果数组,每个元素含 status + value/reason
const results = await Promise.allSettled([
fs.readFile('a.txt'),
fs.readFile('b.txt'),
fs.readFile('c.txt')
]);
const successful = results
.filter(r => r.status === 'fulfilled')
.map(r => r.value);
const failed = results
.filter(r => r.status === 'rejected')
.map(r => r.reason);
✅ 全局兜底:监听未处理的 Promise 拒绝
即使写了 try/catch,仍可能遗漏某些路径(如事件监听器中的 await、定时器回调等)。生产环境务必监听:
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
// 记录日志、告警、或 graceful shutdown
});
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
// 清理资源后退出进程(避免内存泄漏)
process.exit(1);
});
⚠️ 注意:unhandledRejection 不应作为主要错误处理手段,而是最后一道防线。
不复杂但容易忽略










