NestJS for循环内调用异步函数未执行后续逻辑内存报错求助
问题根因
- 核心原因是所有异步IO操作未加
await等待执行:referencedb数据库查询、sendHttpPostHTTP请求均为异步操作,直接调用会返回Promise对象而非实际执行结果。循环会瞬间发起大量未等待的异步任务,大量未完成的任务上下文、Promise对象持续堆积在V8堆内存中,最终触发内存溢出崩溃。 - 语法错误:构造
data对象时使用=赋值属性,JavaScript对象属性赋值应使用:,语法错误会直接导致代码运行中断。 - 内存占用隐患:直接全量读取集合数据,若集合数据量过大,一次性加载全部数据到内存本身会占用大量堆空间,进一步加剧内存溢出风险。
- 循环逻辑隐患:for循环判断条件写为
i != allDataFromCollection.length,如果运行过程中数组长度被意外修改会触发死循环,持续占用CPU和内存直到崩溃。
解决方案
- 给所有异步操作添加
await关键字,等待单个请求完成再执行后续逻辑,避免瞬间高并发请求堆积 - 全量集合查询改为分页查询,每次仅加载少量数据到内存,处理完成后再加载下一批数据,降低内存占用峰值
- 修正对象构造的语法错误,属性赋值改用
: - 将for循环判断条件改为更安全的
i < allDataFromCollection.length,避免意外触发死循环 - 若需提升处理效率,可引入并发限流工具控制同时运行的异步任务数量,避免并发数过高压垮内存、数据库或下游接口
修正后代码示例
@Cron('*/10 * * * * *') async runEvery10Seconds() { console.log("log 1"); // 分页查询配置,可根据实际业务调整单次查询数量 let pageNum = 1; const pageSize = 100; while(true) { // 调用分页查询接口替换原全量查询接口 const allDataFromCollection = await this.findPageData(pageNum, pageSize); // 无数据时终止循环 if (allDataFromCollection.length === 0) break; // 修正循环判断条件 for (let i = 0; i < allDataFromCollection.length; i++) { // 异步数据库查询添加await等待结果返回 const item1Id = await this.referencedb(allDataFromCollection[i].item1value); const item2Id = await this.referencedb(allDataFromCollection[i].item2value); const item3Id = await this.referencedb(allDataFromCollection[i].item3value); // 修正对象属性赋值语法,改用冒号 const data = { item1: item1Id, item2: item2Id, item3: item3Id }; // 异步HTTP请求添加await等待执行完成 await this.sendHttpPost(data); } pageNum++; } }
内容的提问来源于stack exchange,提问作者CarlosMagalhaes
相关产品推荐
相关产品推荐

