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

TypeScript递归调用返回Promise的生成器报最大调用栈溢出如何解决

报错原因

你编写的递归函数为同步递归逻辑:geno.next()返回Promise属于异步执行,但你在发起异步调用后没有等待结果返回,就立刻同步调用genPrinter(geno),相当于无限次同步调用自身,调用栈快速堆积溢出,和异步生成器本身的逻辑无关。

最优解决方案

优先使用ES2018原生支持的for await...of语法遍历异步生成器,这是最简洁、易维护的实现方式,天然适配异步迭代场景:

import { lineOfFileGenerator } from './你的代码文件路径'

async function processLargeFile() {
  // 实例化异步生成器
  const gen = lineOfFileGenerator('./path/to/file');
  // 直接用for await...of遍历,自动处理迭代完成状态
  for await (const line of gen) {
    // 替换为你的业务处理函数即可
    console.log(line);
  }
  console.log('done');
}

// 执行处理逻辑
processLargeFile();

该方案的优势:

  • 语法原生支持,不用手动维护迭代状态
  • 天然支持异步串行执行,不会出现漏行、爆栈问题
  • 错误处理逻辑统一,直接在外部套try/catch即可捕获文件读取、业务处理阶段的所有异常,示例如下:
async function processLargeFile() {
  try {
    const gen = lineOfFileGenerator('./path/to/file');
    for await (const line of gen) {
      console.log(line);
    }
    console.log('done');
  } catch (err) {
    console.error('文件处理失败:', err);
  }
}

备选方案:修复手动递归逻辑

如果你确实需要手动控制迭代过程,只需要把递归调用移到then回调内部,等待当前行处理完成后再触发下一次迭代,就不会出现同步爆栈问题:

function genPrinter(geno: any): void {
  geno.next().then((val: { done: boolean; value: string; }) => {
    if (val.done) {
      console.log('done');
      return;
    }
    // 业务处理逻辑
    console.log(val.value);
    // 处理完当前行再递归调用下一次,不会堆积调用栈
    genPrinter(geno);
  });
}

// 调用时仅需要执行一次即可,不需要主动递归
const gen = lineOfFileGenerator('./path/to/file');
genPrinter(gen);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 12:06:03