Promise.all返回空数组问题:如何解决调用后得到空响应?
解决Promise.all返回空数组的问题
嘿,我帮你找到了问题的根源,咱们一步步来解决它~
问题出在哪?
你的代码里有两个关键错误,直接导致了Promise.all返回空数组:
http.get/https.get不返回Promise:这两个Node.js的API是基于回调的,不是Promise风格的——你用await在这里根本不会等待请求完成,代码会直接跳过回调继续执行,所以你的response数组里压根没东西。response数组没有存入Promise:你试图在回调函数里往response里push字符串,但这时候循环早就跑完了,Promise.all接收的是空数组,自然返回空结果。
解决方案:把回调API包装成Promise
要解决这个问题,我们首先需要把http.get和https.get包装成返回Promise的函数,这样才能用async/await或者Promise.all来正确处理异步流程。
第一步:写包装函数
先把请求API转换成Promise风格:
const http = require('http'); const https = require('https'); // 包装http.get为Promise function httpGet(url) { return new Promise((resolve, reject) => { http.get(url, (res) => { resolve(`${url} - ${res.statusCode}`); }).on('error', (err) => { reject(`请求${url}失败:${err.message}`); }); }); } // 包装https.get为Promise function httpsGet(url) { return new Promise((resolve, reject) => { https.get(url, (res) => { resolve(`${url} - ${res.statusCode}`); }).on('error', (err) => { reject(`请求${url}失败:${err.message}`); }); }); }
第二步:选择合适的执行方式
你有两种选择,根据你的需求来选:
方式1:串行执行请求(一个接一个发起)
如果需要按顺序处理请求,用这种方式:
async function getMessage(arr) { const response = []; // 用for...of循环替代传统for,更清晰 for (const item of arr) { const protocol = item.link.split(':')[0]; let result; try { if (protocol === 'http') { result = await httpGet(item.link); } else { result = await httpsGet(item.link); } response.push(result); } catch (err) { // 捕获单个请求的错误,避免整个函数失败 response.push(err); } } return response; // 直接返回结果数组,不需要再用Promise.all }
方式2:并行执行请求(所有请求同时发起,效率更高)
如果不需要顺序,推荐用这种方式,速度会快很多:
async function getMessage(arr) { // 把每个请求转换成Promise,放进数组 const promiseArr = arr.map(item => { const protocol = item.link.split(':')[0]; if (protocol === 'http') { return httpGet(item.link); } else { return httpsGet(item.link); } }); // 等待所有Promise完成,这里用try/catch捕获全局错误 try { return await Promise.all(promiseArr); } catch (err) { console.error('有请求失败:', err); // 如果想继续获取其他成功的结果,可以用Promise.allSettled // return (await Promise.allSettled(promiseArr)).map(res => res.value || res.reason); } }
额外提醒
- 别忘记处理错误!不管是单个请求还是全局的错误,都要捕获,避免程序崩溃。
- 原代码里的
async (res)回调完全没必要,反而会导致上下文的Promise被忽略,尽量不要在回调里用async/await,除非你明确知道怎么处理它的返回值。
内容的提问来源于stack exchange,提问作者Andrey Radkevich
相关产品推荐
相关产品推荐

