You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在自定义ESLint规则回调中使用async/await的问题

在ESLint自定义规则中处理异步操作的正确方式

ESLint的规则回调默认同步执行,早期版本(v7.0.0之前)不会等待async函数返回的Promise完成,导致你在await后调用context.report()时,ESLint的检查流程已经结束,报告无法生效。即使在支持异步回调的新版本中,单个导入触发异步请求的方式也存在效率问题,以下是两种可行解决方案:

方案一:升级ESLint并使用异步回调(基础版)

若你的ESLint版本≥7.0.0,可直接使用async回调,但需做好错误处理(避免Promise被拒绝导致ESLint忽略后续逻辑):

module.exports = {
    meta: {
        type: "problem",
        docs: {
            description: "This rule checks if any vulnerabilities appear in an imported package"
        },
        fixable: false,
        schema: []
    },
    create(context) {
        return {
            async ImportDeclaration(node) {
                try {
                    const data = await apiCall(node.source.value);
                    // 根据接口返回数据判断是否存在漏洞
                    if (data?.hasVulnerabilities) {
                        context.report({
                            node,
                            message: `Imported package "${node.source.value}" has known vulnerabilities`
                        });
                    }
                } catch (error) {
                    // 捕获并记录错误,避免Promise异常终止规则执行
                    console.error(`Failed to check package ${node.source.value}:`, error);
                }
            }
        };
    }
};

方案二:批量异步处理(推荐版)

通过收集所有需要检查的导入节点,在文件解析完成后(Program:exit钩子)批量发起异步请求,既保证异步操作完成后再报告问题,又能减少API请求次数、提升效率:

module.exports = {
    meta: {
        type: "problem",
        docs: {
            description: "This rule checks if any vulnerabilities appear in an imported package"
        },
        fixable: false,
        schema: []
    },
    create(context) {
        // 收集所有需要检查的导入信息
        const importNodes = [];

        return {
            ImportDeclaration(node) {
                importNodes.push({
                    node,
                    packageName: node.source.value
                });
            },
            // 在文件解析完成后执行批量检查
            async 'Program:exit'() {
                if (importNodes.length === 0) return;

                try {
                    // 并行请求所有包的漏洞信息
                    const checkResults = await Promise.all(
                        importNodes.map(async ({ node, packageName }) => {
                            const data = await apiCall(packageName);
                            return { node, hasVuln: data?.hasVulnerabilities };
                        })
                    );

                    // 统一上报所有存在漏洞的导入
                    checkResults.forEach(({ node, hasVuln }) => {
                        if (hasVuln) {
                            context.report({
                                node,
                                message: `Imported package "${node.source.value}" has known vulnerabilities`
                            });
                        }
                    });
                } catch (error) {
                    console.error('Failed to check package vulnerabilities:', error);
                }
            }
        };
    }
};

额外注意事项

  • 缓存机制:建议对API查询结果添加缓存(如基于包名的内存缓存或文件缓存),避免重复查询同一个包,提升检查速度。
  • 性能影响:异步操作会增加ESLint的检查时间,建议在CI/CD环境或本地开发时根据需求启用该规则。
  • 旧版本兼容:若必须在ESLint v7以下版本使用异步操作,可使用同步HTTP客户端(如sync-request),但这会阻塞ESLint进程,不推荐生产环境使用。

内容的提问来源于stack exchange,提问作者Rj 45

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:44:53