Node.js 异步错误处理
异步错误处理方式取决于异步机制类型。
回调风格错误处理
Error-First 回调
JavaScript
// Node.js 标准:第一个参数为错误
fs.readFile('file.txt', (err, data) => {
if (err) {
console.error('读取失败:', err);
return; // 必须 return,停止执行
}
console.log('内容:', data);
});
多层回调
JavaScript
fs.readFile('file1.txt', (err1, data1) => {
if (err1) return handleError(err1);
fs.readFile('file2.txt', (err2, data2) => {
if (err2) return handleError(err2);
processData(data1, data2, (err3, result) => {
if (err3) return handleError(err3);
console.log(result);
});
});
});
自定义异步函数
JavaScript
function asyncOperation(input, callback) {
try {
const result = doSomething(input);
callback(null, result); // 成功:null + 结果
} catch (err) {
callback(err); // 失败:错误 + 无结果
}
}
// 使用
asyncOperation('input', (err, result) => {
if (err) {
console.error(err);
return;
}
console.log(result);
});
Promise 错误处理
.catch 方法
JavaScript
fs.promises.readFile('file.txt')
.then(data => {
console.log('内容:', data);
})
.catch(err => {
console.error('读取失败:', err);
});
链式 catch
JavaScript
fs.promises.readFile('file1.txt')
.then(data1 => fs.promises.readFile('file2.txt'))
.then(data2 => processData(data1, data2))
.then(result => console.log(result))
.catch(err => {
// 捕获链条中所有错误
console.error('某步骤失败:', err);
});
.then 第二参数
JavaScript
fs.promises.readFile('file.txt')
.then(
data => console.log(data), // 成功
err => console.error(err) // 失败
);
中间处理
JavaScript
fs.promises.readFile('file.txt')
.then(data => {
return processData(data);
})
.catch(err => {
// 处理读取错误,返回默认值继续
console.warn('使用默认数据');
return getDefaultData();
})
.then(result => {
console.log('最终结果:', result);
});
async/await 错误处理
try/catch 捕获
JavaScript
async function readFile() {
try {
const data = await fs.promises.readFile('file.txt');
const result = await processData(data);
console.log(result);
} catch (err) {
console.error('处理失败:', err);
}
}
多步骤处理
JavaScript
async function processFiles() {
try {
const data1 = await fs.promises.readFile('file1.txt');
const data2 = await fs.promises.readFile('file2.txt');
const result = await combine(data1, data2);
return result;
} catch (err) {
console.error('失败:', err.message);
throw err; // 重新抛出给调用者
}
}
错误恢复
JavaScript
async function getData() {
try {
return await fetchFromAPI();
} catch (err) {
// API 失败,使用缓存
console.warn('API 失败,读取缓存');
return await readFromCache();
}
}
并行操作错误处理
JavaScript
async function parallel() {
try {
const [a, b, c] = await Promise.all([
fetchA(),
fetchB(),
fetchC()
]);
return combine(a, b, c);
} catch (err) {
// 任意一个失败都会触发
console.error('并行任务失败:', err);
}
}
// 忽略部分失败
async function partialSuccess() {
const results = await Promise.allSettled([
fetchA(),
fetchB(),
fetchC()
]);
results.forEach((result, i) => {
if (result.status === 'fulfilled') {
console.log(`任务 ${i} 成功:`, result.value);
} else {
console.error(`任务 ${i} 失败:`, result.reason);
}
});
}
三种方式对比
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 回调 | 简单直接 | 嵌套复杂、易遗漏 | 简单异步操作 |
| Promise | 链式清晰、可组合 | 状态理解需学习 | 多步骤流程 |
| async/await | 同步风格、直观 | 需理解 Promise | 复杂业务逻辑 |
错误传播
回调传播
JavaScript
function outer(callback) {
inner((err, result) => {
if (err) return callback(err); // 传播错误
callback(null, result);
});
}
Promise 自动传播
JavaScript
function outer() {
return inner()
.then(result => process(result));
// inner 错误自动传播到 outer 的调用者
}
async 自动传播
JavaScript
async function outer() {
const result = await inner();
return process(result);
// inner 错误自动抛出
}
注意事项
- 回调必须检查
err并 return- Promise 链末尾必须有
.catch()- async 函数必须用 try/catch 或外层 catch
Promise.all一个失败全部失败Promise.allSettled可处理部分失败
要点总结
- 回调:Error-First,检查 err 后 return
- Promise:使用
.catch()捕获链错误 - async/await:使用 try/catch 捕获
- Promise.allSettled 处理部分失败
- 错误必须传播或处理,不能遗漏
📝 发现内容有误?点击此处直接编辑