面试题答案
一键面试异常处理方式及优缺点
- 在
async
函数内部使用try...catch
- 代码示例:
async function asyncIterate() {
const asyncIterable = {
async *[Symbol.asyncIterator]() {
yield Promise.resolve(1);
yield Promise.reject(new Error('模拟错误'));
yield Promise.resolve(3);
}
};
try {
for await (const value of asyncIterable) {
console.log(value);
}
} catch (error) {
console.error('捕获到错误:', error.message);
}
}
asyncIterate();
- **优点**:简单直接,可以捕获整个`async`函数执行过程中的所有异常,包括异步迭代过程中的异常。
- **缺点**:如果`async`函数中有多个异步操作,一旦捕获到异常,整个`async`函数后续的异步操作都会停止,无法对不同阶段的异常进行更细粒度的处理。
2. 在yield
的Promise
上使用.catch
- 代码示例:
async function asyncIterate() {
const asyncIterable = {
async *[Symbol.asyncIterator]() {
yield Promise.resolve(1);
yield Promise.reject(new Error('模拟错误'));
yield Promise.resolve(3);
}
};
for await (const value of asyncIterable) {
value.catch(error => {
console.error('捕获到错误:', error.message);
}).then(data => {
if (data) {
console.log(data);
}
});
}
}
asyncIterate();
- **优点**:可以对每个`yield`的`Promise`进行单独的异常处理,不会影响其他`yield`的`Promise`执行,能够实现更细粒度的控制。
- **缺点**:代码相对繁琐,需要为每个`yield`的`Promise`都添加`.catch`处理,并且如果忘记添加`.catch`,异常可能会导致未处理的拒绝(unhandled rejection)。
优化方案
可以结合上述两种方式,在async
函数内部使用try...catch
捕获整体异常,同时在可能出现错误的关键yield
的Promise
上使用.catch
进行局部异常处理,并且在.catch
中可以选择抛出更有意义的错误以便外层try...catch
统一处理。
代码示例:
async function asyncIterate() {
const asyncIterable = {
async *[Symbol.asyncIterator]() {
yield Promise.resolve(1);
yield Promise.reject(new Error('模拟错误'));
yield Promise.resolve(3);
}
};
try {
for await (const value of asyncIterable) {
value.catch(error => {
console.error('局部捕获到错误:', error.message);
// 可以选择抛出更有意义的错误
throw new Error('处理后的错误');
}).then(data => {
if (data) {
console.log(data);
}
});
}
} catch (error) {
console.error('整体捕获到错误:', error.message);
}
}
asyncIterate();
这样既可以在局部对可能失败的异步操作进行处理,又能在整体上确保不会遗漏异常,提高程序的健壮性。