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

为何递归Promise链一个引发内存泄漏,另一个却不会?

为什么返回Promise的递归链会导致内存泄漏,而不返回的不会?

我有两段逻辑看似一致的递归Promise循环代码,但其中一段会引发内存泄漏,另一段不会。简化后的代码如下:

泄漏代码:

function leakingLoop() {
  return delay(1)
  .then(() => {
    console.log(`Tick ${Date.now()}`)
    return leakingLoop()
  })
}

无泄漏代码:

function nonLeakingLoop() {
  delay(1)
    .then(() => {
      console.log(`Tick ${Date.now()}`)
      nonLeakingLoop()
    })
}

两者唯一的区别是leakingLoop会返回delay Promise的执行结果,而nonLeakingLoop不返回。请问为什么leakingLoop会导致内存泄漏?是不是我忽略了Promise的某些机制?

注:假设delay是一个指定时长后resolve的Promise函数,如果这个假设不符合实际,请告知我更新问题。


核心原因:Promise的链式引用与垃圾回收

这本质是因为返回Promise会构建一条无限延伸的Promise链,每个Promise都会保留对前一个Promise的引用,而不返回的版本里,每个Promise完成后没有被外部引用,能被垃圾回收器及时清理。

具体拆解:

  • 在leakingLoop中,每次调用leakingLoop()都会返回一个新的Promise,这个Promise是上一个delay().then(...)的返回值。Promise的then方法会创建新Promise,且新Promise会持有对原Promise(delay返回的实例)以及回调函数的引用。由于递归时把leakingLoop()的结果返回给上层then,这就形成了Promise1 -> Promise2 -> Promise3 -> ...的无限链式结构,每个后续Promise都依赖前一个节点,导致所有之前的Promise都无法被垃圾回收,内存持续累积。

  • 而nonLeakingLoop里,delay().then(...)的结果没有被返回,意味着这个Promise没有被任何外部变量或上层Promise引用。当then回调执行完毕后,当前Promise对象就没有活跃引用了,垃圾回收器可以正常回收它占用的内存。每次递归调用nonLeakingLoop都是独立创建新的Promise,不会形成链式引用,因此不会有内存泄漏。

简单总结:返回Promise会让整个链的所有节点都被保留,不返回则每个节点用完就被回收。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 20:02:34