在自定义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
相关产品推荐
相关产品推荐

