You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

async/await递归无法在主函数中完成Promise解析问题求助

解决async/await递归中Promise无法resolve的问题

咱来瞅瞅你代码里的问题——核心是recursion函数的写法踩了两个坑,导致整个Promise链一直处于pending状态,main函数里的await永远等不到最终结果:

问题拆解

  1. 冗余的手动Promise嵌套recursion本身就是async函数,async函数会自动把返回值包装成Promise,完全没必要再手动return new Promise(...),这种嵌套很容易遗漏resolve逻辑。
  2. 递归分支未resolve外层Promise:在else分支里,你调用了await recursion(i),但外层那个手动创建的Promise从来没被resolve(除了i=0的情况)。举个例子:当i=1时,递归调用recursion(0)会resolve,但recursion(1)自己的Promise没被resolve,导致recursion(2)await拿不到结果,层层往上,最终main里的await recursion(3)一直卡着。

修正方案

方案1:利用async函数的天然Promise特性(推荐)

直接去掉手动包裹的Promise,让async函数自己处理Promise返回,代码更简洁不易错:

async function delay(ms) {
  return await new Promise(resolve => setTimeout(resolve, ms))
}

async function recursion(i) {
  if (i == 0) {
    console.log(`i == 0`)
    return i; // async函数中return的值会自动作为Promise的resolve结果
  } else {
    console.log(`i = ${i}. Wait 2 seconds...`)
    i--
    await delay(2000)
    return recursion(i); // 返回递归的Promise,让上层await能获取结果
  }
}

async function main() {
  let i = await recursion(3)
  console.log(`END OF RECURSION`)
  console.log(`i => ${i}`)
}

main()

方案2:保留手动Promise(不推荐,但可以作为理解参考)

如果非要手动创建Promise,必须确保每个分支都调用resolve,把递归的结果传递出去:

async function delay(ms) {
  return await new Promise(resolve => setTimeout(resolve, ms))
}

async function recursion(i) {
  return new Promise(async (resolve, reject) => {
    if (i == 0) {
      console.log(`i == 0`)
      resolve(i)
    } else {
      console.log(`i = ${i}. Wait 2 seconds...`)
      i--
      await delay(2000)
      const result = await recursion(i)
      resolve(result); // 必须resolve递归结果,否则外层Promise永远pending
    }
  })
}

async function main() {
  let i = await recursion(3)
  console.log(`END OF RECURSION`)
  console.log(`i => ${i}`)
}

main()

运行修正后的代码,你就能看到END OF RECURSIONi => 0的输出啦~

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

火山引擎 最新活动