MST
星途 面试题库

面试题:Node.js异步迭代器中async/await的异常处理优化

在Node.js异步迭代器使用async/await进行异步操作时,如何优雅地处理可能出现的各种异常,以确保程序的健壮性。请结合实际代码,说明不同异常处理方式的优缺点,并提出一种优化方案。
35.5万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

异常处理方式及优缺点

  1. 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. yieldPromise上使用.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捕获整体异常,同时在可能出现错误的关键yieldPromise上使用.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();

这样既可以在局部对可能失败的异步操作进行处理,又能在整体上确保不会遗漏异常,提高程序的健壮性。