如何从Promise数组获取API响应的JSON结果并聚合?
解决方案:批量API调用并聚合JSON响应
问题分析
第一种尝试的问题
你的callAPI函数直接返回了fetch的Response对象,并没有解析响应体的JSON内容。所以Promise.all最终得到的是一组Response实例,而非你需要的JSON数据。
第二种尝试的问题
你在map循环中发起异步请求,但没有收集这些请求的Promise对象,也没有等待它们完成。solve函数会直接返回空的projects数组,因为异步请求还没执行完,push操作还没触发。
修复方案
方案1:修改callAPI函数(推荐)
让callAPI直接返回解析后的JSON数据,上层调用无需再处理响应解析:
export const callAPI = async (path, body, method = "GET") => { const config = { method: method, headers: { "Content-Type": "application/json", }, }; if (body) { config.body = JSON.stringify(body); } const URL = `${process.env.HOST}${path}`; const response = await fetch(URL, config); // 校验请求状态并解析JSON if (!response.ok) { throw new Error(`请求失败: ${response.status}`); } return await response.json(); };
此时第一种尝试的代码可直接使用,res即为聚合后的JSON数组:
const getProjectData = async (projectID) => await callAPI(`/projects/${projectID}`); const solve = async () => { const projectsPromises = currentUserProjectIDs.map(project => getProjectData(project)); return await Promise.all(projectsPromises); }; const res = await solve(); console.log("res", res); // 输出所有JSON响应组成的数组
方案2:不修改callAPI,在请求层解析JSON
如果不想改动callAPI,可以在getProjectData中添加JSON解析步骤:
const getProjectData = async (projectID) => { const response = await callAPI(`/projects/${projectID}`); if (!response.ok) { throw new Error(`请求失败: ${response.status}`); } return response.json(); }; const solve = async () => { const projectsPromises = currentUserProjectIDs.map(project => getProjectData(project)); return await Promise.all(projectsPromises); }; const res = await solve(); console.log("res", res);
方案3:修复第二种尝试的代码
若偏好then链式调用,需收集所有请求的Promise并通过Promise.all等待完成:
const solve = async () => { // 收集每个请求的Promise const projectPromises = currentUserProjectIDs.map((p) => { return callAPI(`/projects/${p}`) .then((r) => r.json()) .then((a) => { console.log("a", a); return a; }); }); // 等待所有请求完成后返回结果数组 return await Promise.all(projectPromises); }; const prj = await solve(); console.log("prj", prj); // 输出聚合后的JSON数组
关键注意点
- 务必处理
fetch的错误情况(比如通过response.ok判断请求状态),避免单个请求失败导致整个流程崩溃。 - 若希望某个请求失败不影响其他结果,可使用
Promise.allSettled替代Promise.all,之后过滤出成功的响应即可。
内容的提问来源于stack exchange,提问作者gusti
相关产品推荐
相关产品推荐

