MST
星途 面试题库

面试题:Node.js 自定义错误类在复杂异步流程中的应用及优化

在一个涉及多个异步操作(如多个数据库查询、文件读写等)的Node.js项目中,使用自定义错误类来处理整个流程中的错误。要求考虑如何在不同的异步操作环节抛出和捕获自定义错误,确保错误处理的一致性和高效性,同时避免内存泄漏等潜在问题。请详细阐述实现思路并给出关键代码示例。
28.9万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 定义自定义错误类:继承 Error 类创建自定义错误类,以便在不同异步操作中抛出特定类型错误。
  2. 异步操作中的错误抛出:在每个异步操作(如数据库查询、文件读写)中,使用 try - catch 块捕获原生错误,并将其转换为自定义错误抛出。如果使用的是 Promise 风格的异步操作,可通过 reject 抛出自定义错误。
  3. 错误捕获与处理:在整个异步流程的上层,使用 try - catch 块或 .catch() 方法(针对 Promise)捕获自定义错误,进行统一的错误处理。确保在错误处理完成后,释放相关资源,避免内存泄漏。

关键代码示例

// 定义自定义错误类
class CustomError extends Error {
    constructor(message) {
        super(message);
        this.name = 'CustomError';
    }
}

// 模拟异步数据库查询
function asyncDbQuery() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            // 模拟查询失败
            const shouldFail = true;
            if (shouldFail) {
                reject(new CustomError('数据库查询失败'));
            } else {
                resolve('查询结果');
            }
        }, 1000);
    });
}

// 模拟异步文件读写
function asyncFileRead() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            // 模拟文件读取失败
            const shouldFail = true;
            if (shouldFail) {
                reject(new CustomError('文件读取失败'));
            } else {
                resolve('文件内容');
            }
        }, 1000);
    });
}

// 主异步流程
async function main() {
    try {
        const dbResult = await asyncDbQuery();
        const fileResult = await asyncFileRead();
        console.log('操作成功:', dbResult, fileResult);
    } catch (error) {
        if (error instanceof CustomError) {
            console.error('自定义错误:', error.message);
        } else {
            console.error('其他错误:', error.message);
        }
    }
}

main();

内存泄漏预防

  1. 资源释放:在异步操作完成或出错时,确保及时关闭数据库连接、文件句柄等资源。例如在数据库查询完成或出错时,使用 connection.end() 关闭数据库连接;在文件读写完成或出错时,使用 fs.close() 关闭文件句柄。
  2. 事件监听器移除:如果在异步操作中添加了事件监听器,在操作完成或出错时,确保移除这些监听器,防止因重复添加监听器导致内存泄漏。例如使用 emitter.removeListener(eventName, listener) 移除事件监听器。