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
相关产品推荐
相关产品推荐

