ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

eslint-plugin-unicorn 规则详解:no-await-in-promise-methods 禁止在 Promise 聚合方法参数中使用 await

eslint-plugin-unicorn 规则详解:no-await-in-promise-methods 禁止在 Promise 聚合方法参数中使用 await eslint-plugin-unicorn 规则详解no-await-in-promise-methods 禁止在 Promise 聚合方法参数中使用 await【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn导读no-await-in-promise-methods是 eslint-plugin-unicorn 提供的 ESLint 规则专门拦截Promise.all()、Promise.allSettled()、Promise.any()、Promise.race()这类聚合方法参数中出现await的写法。本指南将从规则用途、完整示例、边界场景到源码实现逐层拆解帮助你理解该规则为什么存在、如何生效、覆盖哪些场景以及如何在项目中正确配置与使用。规则概览它到底在检查什么Promise.all()等聚合方法本身就接收 Promise 对象并负责统一等待因此把已经await过的值再传进去是典型的冗余甚至错误的写法。该规则会在以下四种静态方法调用中检查其数组参数里的每一个元素Promise.all()Promise.allSettled()Promise.any()Promise.race()一旦发现数组中存在await表达式规则即报告错误并通过 ESLint editor suggestions编辑器建议 提供一键移除await的修复方案注意是手动可触发的 suggestion而非自动 fix。根据文档头部说明该规则默认启用✅recommended同时也属于 ☑️unopinionated配置集。从规则元数据rules/no-await-in-promise-methods.js可以看到其完整定义type: suggestion、hasSuggestions: true、docs.recommended: unopinionated、支持语言为js/js这与文档描述完全一致。为什么这是错误写法Promise.all([p1, p2])的语义是“同时等待 p1、p2全部完成后统一继续”数组内的 Promise 是并行等待的。而如果写成Promise.all([await p1, p2])await p1会先把 p1 串行等待完成之后才构造出数组并调用Promise.all聚合方法的并行优势被完全破坏对已经 resolve 的值再交给Promise.all没有任何额外价值属于冗余操作如果该await位于非 async 上下文中还会直接报语法错误即使位于 async 上下文中也是把本应交给聚合方法统一处理的 Promise 提前拆解。因此正确做法是直接把 Promise 引用传入数组让Promise.all()等方法自行统一等待。完整示例错误与正确写法对比以下四组示例完整覆盖该规则检查的四种方法对应文档 docs/rules/no-await-in-promise-methods.md 中的示例// ❌ 错误 Promise.all([await promise, anotherPromise]); // ✅ 正确 Promise.all([promise, anotherPromise]);// ❌ 错误 Promise.allSettled([await promise, anotherPromise]); // ✅ 正确 Promise.allSettled([promise, anotherPromise]);// ❌ 错误 Promise.any([await promise, anotherPromise]); // ✅ 正确 Promise.any([promise, anotherPromise]);// ❌ 错误 Promise.race([await promise, anotherPromise]); // ✅ 正确 Promise.race([promise, anotherPromise]);源码级解析规则如何精准命中第一步识别“Promise 聚合方法调用 数组参数”规则核心位于 rules/no-await-in-promise-methods.js它先通过isPromiseMethodCallWithArrayExpression做前置过滤L12-L20要求同时满足是方法调用且对象为Promise方法名属于[all, allSettled, any, race]见 L10 的METHODS常量optionalMember: false、optionalCall: false即不能是Promise?.all(...)/Promise.all?.(...)这类可选链写法argumentsLength: 1即恰好只有一个参数多传参数或零参数不检查第一个参数的类型必须是ArrayExpression数组字面量。这里的isMethodCall是插件中复用率最高的 AST 判断工具之一其完整实现见 rules/ast/is-method-call.js它会先快速排除非CallExpression/MemberExpression形状的节点再按方法名matchesNameConstraint、调用形式isCallExpression支持argumentsLength、minimumArguments、optional等选项与成员表达式isMemberExpression支持object、computed、optional等选项逐层校验。第二步遍历数组元素命中 AwaitExpression通过前置过滤后规则在CallExpression事件L26中遍历callExpression.arguments[0].elementsL31-L33只要某个元素类型是AwaitExpression就上报一条错误错误消息为Promise in Promise.{{method}}() should not be awaited.其中{{method}}会替换为实际的方法名all、allSettled、any或race因此报告信息能精确指出是哪一个聚合方法L36-L41。第三步suggestion 修复——安全移除 await每条错误附带一条 suggestionRemove await.其修复逻辑L42-L51为取得await关键字对应的第一个 token调用fixer.remove()移除await本身调用removeSpacesAfter一并移除await与后续表达式之间的空白。removeSpacesAfter的实现位于 rules/fix/remove-spaces-after.js它取 token 结束位置之后紧邻的空白字符区间/^\s*/并将其一并删除从而保证[await promise]被干净地整理为[promise]不会留下多余空格或换行痕迹。边界场景哪些写法会被检查哪些不会该规则的判定边界在测试文件 test/no-await-in-promise-methods.js 中有完整的快照式覆盖可以按“报错 / 放行”两个维度归纳。会报错的典型场景Promise.all([await promise]); // 单个 await Promise.all([, await promise]); // 数组空洞 await Promise.all([await promise,]); // 带尾逗号 Promise.all([await (0, promise)]); // await 包装序列表达式 Promise.all([await (( promise ))]); // 多余括号 Promise.all([await await promise]); // 双重 await Promise.all([...foo, await p1, await p2]); // 展开元素与 await 混用 Promise.all([await promise1, await promise2]); // 多个 await 元素 Promise.any([await a, await b, await c]); Promise.all([await /* comment*/ promise]); // await 后带注释明确放行不检查的场景Promise.all([promise1, promise2, promise3, promise4]); // 无 await天然正确 Promise.all(...[await promise]); // 展开调用而非数组字面量参数 Promise.all([await promise], extraArguments); // 参数多于一个 Promise.all(); // 无参数 Promise.all(notArrayExpression); // 参数不是数组字面量 Promise.all([,]); // 空数组空洞 Promiseall; // 计算属性成员 Promise.all?.([await promise]); // 可选调用 Promise?.all([await promise]); // 可选成员 Promise.notListedMethod([await promise]); // 非目标方法 NotPromise.all([await promise]); // 对象不是 Promise Promise.all([(await promise, 0)]); // await 藏在序列表达式内部 new Promise.all([await promise]); // new 调用 // 明确不检查的边界 globalThis.Promise.all([await promise]); // 通过 globalThis 访问 Promiseall; // 字符串计算属性访问其中globalThis.Promise.all与Promise[all]在测试中被明确标注为“We are not checking these cases”即该规则只处理字面量Promise.all(...)这种直接成员访问的形态。这些精确的边界划分全部由上述isMethodCall的选项optionalMember: false、optionalCall: false、argumentsLength: 1等与“参数必须是ArrayExpression”的双重校验保证。在项目中启用与使用该规则已包含在recommended与unopinionated配置集中使用对应配置即可直接生效// eslint.config.jsflat config import unicorn from eslint-plugin-unicorn; export default [ unicorn.configs[recommended], // 或 unicorn.configs.unopinionated ];若项目未启用整个配置集也可以单独开启export default [ { plugins: {unicorn}, rules: { unicorn/no-await-in-promise-methods: error, }, }, ];当规则报错时在支持 ESLint suggestions 的编辑器VSCode 等中触发“Quick Fix”选择Remove await.即可一键完成修复修复逻辑正是上文介绍的 token 删除与空白清理流程。小结no-await-in-promise-methods是一个小而精准的规则它通过isMethodCall严格限定Promise.all/allSettled/any/race的单参数数组字面量调用形态逐元素扫描AwaitExpression并以 suggestion 方式提供安全修复。理解其前置过滤条件与边界用例能帮助你准确预判规则行为写出更符合并行语义的 Promise 聚合代码。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表