Node.js中for循环异步请求致Promise无法Resolve的问题
问题:Node.js Promise无法resolve,循环变量输出异常
我写了一段Node.js代码,想用for循环发起多个异步请求填充数组,然后在数组填充完成后resolve Promise,但循环里的变量i始终只输出0、1或3,Promise永远无法触发resolve。代码如下:
const InvType = ["Hat", "Face", "FaceAccessory", "HairAccessory", "BackAccessory", "NeckAccessory", "FrontAccessory", "WaistAccessory", "Gear"] var Prom = new Promise((resolve, reject) => { var Inv = [] for (let i = 0; i < InvType.length; i++) { https.get('https://inventory.roblox.com/v1/users/111138402/assets/collectibles?assetType=' + InvType[i] + '&sortOrder=Asc&limit=100', (resp) => { let data = ''; resp.on('data', (chunk) => { data += chunk; }); resp.on('end', () => { var arrayLength = JSON.parse(data).data.length; for (var v = 0; v < arrayLength; v++) { Inv.concat(JSON.parse(data).data[v]) console.log(i) } if (i >= 9) { resolve(Inv) } }); }).on("error", (err) => { console.log("Error: " + err.message); }); } })
我希望所有数据都获取完成后再resolve,避免后续代码提前执行,求帮忙排查问题。
问题分析与解决方案
核心问题点
- 判断条件错误:
InvType的长度是9,数组索引从0到8,所以i的最大值是8,i >=9的条件永远不会成立,这是Promise无法resolve的直接原因。 - 异步请求的并发无序性:
https.get是异步操作,循环会一次性发起所有请求,但回调函数的执行顺序不固定(取决于接口响应速度),所以你看到的i输出0、1、3是因为这些请求先返回了,其他请求还处于pending状态。 - 数组拼接错误:
Inv.concat(...)不会修改原数组Inv,而是返回一个新数组,所以你的Inv始终是空数组,数据根本没被存进去。 - 未跟踪所有请求完成状态:当前逻辑只在单个请求回调里判断是否resolve,但无法保证所有请求都已完成。
修复方案
把每个异步请求包装成独立的Promise,用Promise.all等待所有请求完成后再统一处理数据并resolve,这样能确保所有数据都获取完毕后才执行后续逻辑。
修改后的代码:
const https = require('https'); const InvType = ["Hat", "Face", "FaceAccessory", "HairAccessory", "BackAccessory", "NeckAccessory", "FrontAccessory", "WaistAccessory", "Gear"]; // 把单个请求包装成Promise function fetchInventory(type) { return new Promise((resolve, reject) => { const url = `https://inventory.roblox.com/v1/users/111138402/assets/collectibles?assetType=${type}&sortOrder=Asc&limit=100`; https.get(url, (resp) => { let data = ''; resp.on('data', (chunk) => data += chunk); resp.on('end', () => { try { const result = JSON.parse(data); resolve(result.data || []); // 直接返回数据数组,后续统一合并 } catch (err) { reject(err); } }); }).on("error", reject); }); } // 用Promise.all等待所有请求完成 const Prom = Promise.all(InvType.map(type => fetchInventory(type))) .then(allData => { // 合并所有请求返回的数组 const Inv = allData.flat(); // flat可以把二维数组转成一维 return Inv; }) .catch(err => { console.error('请求出错:', err.message); throw err; // 抛出错误让后续处理 }); // 后续使用示例 Prom.then(inventory => { console.log('完整 inventory:', inventory); }).catch(err => { console.error('处理失败:', err); });
关键改进点
- 每个请求独立封装成Promise,逻辑更清晰,也方便错误处理
- 用
Promise.all自动等待所有请求完成,无需手动计数 - 用
flat()合并所有返回的数组,替代原有的循环拼接,更简洁 - 修复了数组拼接的问题,确保数据能正确存入
- 统一处理解析JSON的异常,避免单个请求出错导致整个流程卡住
内容的提问来源于stack exchange,提问作者me7474
相关产品推荐
相关产品推荐

