Promise 和 try-catch 不是同一层面的东西 ,它们解决不同的问题,但经常被放在一起比较的是 Promise 的错误处理(.catch) 和 try-catch 同步错误捕获。
核心区别
| 特性 | try-catch | Promise.catch |
|---|---|---|
| 捕获错误类型 | 同步代码 | 异步代码(Promise 链) |
| 语法 | 语句块 | 方法链 |
| 能否捕获异步错误 | ❌ 不能 | ✅ 能 |
关键示例:try-catch 无法捕获异步错误
javascript
// ❌ try-catch 无法捕获异步错误
try {
setTimeout(() => {
throw new Error('异步错误'); // 这里抛出错误时,try-catch早已执行完毕
}, 1000);
} catch (err) {
console.log('捕获不到:', err); // 永远不会执行
}
// ✅ Promise.catch 可以捕获
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('异步错误')); // 通过 reject 传递错误
}, 1000);
});
promise.catch(err => {
console.log('捕获到了:', err); // 能捕获
});
// ✅ 或者使用 async/await + try-catch
async function test() {
try {
await promise; // await 把异步错误转成了可捕获的同步错误
} catch (err) {
console.log('用 try-catch 也能捕获了', err);
}
}
各自的使用场景
try-catch 适合:
javascript
// 1. 同步代码
try {
JSON.parse('invalid json');
const result = 1 / 0;
if (someVar === undefined) throw new Error('自定义错误');
} catch (err) {
console.error(err);
}
// 2. async/await 中的异步代码
async function fetchData() {
try {
const response = await fetch('/api/user');
const data = await response.json();
return data;
} catch (err) {
console.log('请求失败', err);
}
}
Promise.catch 适合:
javascript
// 1. Promise 链式调用
fetch('/api/user')
.then(res => res.json())
.then(data => processData(data))
.catch(err => {
console.error('某个环节出错', err);
});
// 2. 多个独立的 Promise(Promise.all)
Promise.all([
fetch('/api/user'),
fetch('/api/posts'),
fetch('/api/comments')
])
.then(results => console.log('全部成功', results))
.catch(err => console.log('任意一个失败', err));
混合使用的常见模式
javascript
// 在 async 函数中,可以用 try-catch 代替 .catch
async function getData() {
try {
const user = await fetchUser(); // 可能 reject
const posts = await fetchPosts(); // 可能 reject
return { user, posts };
} catch (error) {
// 统一处理任何一个 await 的错误
console.error('出错了:', error);
return null;
}
}
// 等价于 Promise 写法
function getData() {
return fetchUser()
.then(user => Promise.all([user, fetchPosts()]))
.then(([user, posts]) => ({ user, posts }))
.catch(error => {
console.error('出错了:', error);
return null;
});
}
实际项目中的推荐写法
javascript
// 1. 顶层异步函数:用 try-catch(更清晰)
async function handleRequest() {
try {
const data = await apiCall();
updateUI(data);
} catch (err) {
showErrorToast(err.message);
} finally {
hideLoading(); // 无论成功失败都执行
}
}
// 2. 链式操作较多时:用 .catch(更链式)
apiCall()
.then(transformData)
.then(validateData)
.then(saveToStore)
.catch(handleError);
// 3. 同时捕获同步和异步错误
async function robustFunction() {
try {
// 同步错误也能捕获
if (!input) throw new Error('输入为空');
// 异步错误也能捕获
const result = await asyncOperation();
return result;
} catch (err) {
// 统一处理所有错误
return fallbackValue;
}
}
总结
- 不能互相替代:try-catch 管同步,Promise.catch 管异步 Promise
- 最佳实践 :使用
async/await + try-catch能让异步代码看起来像同步代码,错误处理也更统一 - 记住 :
await是关键,它把 Promise 的 reject 转换成了可以被 try-catch 捕获的异常