首页/开发/代码质量与评审速查/no-floating-promises:别让 Promise 悬空
规范与静态检查65 条

no-floating-promises:别让 Promise 悬空

未处理的 Promise 会导致错误被吞、执行顺序错乱:typescript-eslint 的 no-floating-promises 规则要求 await、显式 void 或统一错误处理。

悬空 Promise 是什么

悬空 Promise(floating promise)指调用了一个返回 Promise 的函数,却没有 await、没有 then 与 catch,也没有显式标记忽略:异步任务照跑,失败却无人接收,错误被静默吞掉,执行顺序也不再与代码书写顺序一致。TypeScript 项目里由 typescript-eslint 的 no-floating-promises 规则负责拦截。

基本信息

问题表现Promise 未 await 也未 catch
对应规则@typescript-eslint/no-floating-promises
前置条件需要类型信息,必须配置类型感知的 lint
修复方式await、显式 void,或统一收集并处理

典型使用场景

  • 事件回调里调用 async 函数:失败没有 catch,异常消失在控制台之外
  • 初始化逻辑漏了 await:后续代码在数据就绪前就开始执行
  • 批量任务并发启动:需要用 Promise.all 或 allSettled 统一处理结果
  • 确实不关心结果的场景:显式写 void,并加注释说明理由
  • 埋点与日志这类火并忘调用:同样要保证失败不会中断主流程

启用与治理顺序

  • 先在 CI 打开类型感知的 lint,否则规则不会生效
  • 按目录逐步启用,避免一次报出成百上千条
  • 为确实要忽略的调用补上 void 与理由注释
  • 在统一入口收集未处理的拒绝,避免进程静默退出

对比写法

对比写法
// 不好:失败无人知晓
loadUser();

// 好:显式等待
const user = await loadUser();

// 并发场景统一处理
const results = await Promise.allSettled([loadUser(), loadOrders()]);

// 明确忽略,需在评审中说明理由
void refreshCache();

同族规则与拦截范围

规则拦截的问题
no-floating-promisesPromise 被创建后无人处理
no-misused-promisesasync 函数被放进期望返回 void 的位置
await-thenable对非 Promise 值使用 await
require-awaitasync 函数体内没有任何 await
这条规则依赖类型信息:只做语法层面的检查不会生效,必须把类型感知的 lint 配置接进流水线。
运行时可以监听未处理的拒绝作为兜底,但它只用来发现漏网之鱼,不能替代逐处显式处理。
用 void 批量消除告警:真实存在的并发与错误处理问题会被一起掩盖掉。

易错点

  • 用 void 批量消除告警:掩盖真实的并发与错误处理问题
  • 只在部分目录启用规则:漏检的文件继续静默吞掉错误
  • 把规则当作纯风格问题:未处理的拒绝往往以进程退出或数据不一致的形式暴露
  • 在事件回调里随意调用 async 函数:错误既没有 catch 也没有日志,只能靠现象反推
  • 把返回 Promise 的函数当同步调用:后续逻辑先于数据就绪执行,出现难以复现的空值错误

数据来源与参考

  • typescript-eslint 文档 · no-floating-promises 规则
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌