使用Promise.all实现15个API并发调用失败,求排查问题
问题:Promise.all并发调用API无输出且无报错
我正在学习JavaScript Promise与API调用,已经用Promise.then和async/await两种方式实现了15个串行API调用获取图片并渲染到容器的功能。现在尝试改用Promise.all实现并发调用,但新代码没有页面输出,控制台也没报错,找不到问题所在。
可正常运行的串行实现(仅使用Promise)
const getImage = function () { fetch("https://api.api-ninjas.com/v1/randomimage", { method: "GET", headers: { "X-API-Key": "###", Accept: "image/jpg", }, }) .then((response) => { if (!response.ok) throw new Error("Network failure"); return response.blob(); }) .then((blob) => { const img = document.createElement("img"); img.src = URL.createObjectURL(blob); container.append(img); }) .catch((err) => console.error(`${err.message}`)); };
可正常运行的串行实现(async/await)
const getImage = async function () { try { const response = await fetch("https://api.api-ninjas.com/v1/randomimage/", { method: "GET", headers: { "X-API-Key": "###", Accept: "image/jpg", }, }); if (!response.ok) throw new Error(`Network failure! Status: ${response.status}`); const data = await response.blob(); const img = document.createElement("img"); img.src = URL.createObjectURL(data); container.append(img); } catch (err) { console.error(`${err.message}`); } };
存在问题的并发调用代码
const getImage = function () { fetch("https://api.api-ninjas.com/v1/randomimage", { method: "GET", headers: { "X-API-Key": "###", Accept: "image/jpg", }, }); }; const firstImages = async function () { try { const res = await Promise.all([ getImage(), getImage(), getImage(), getImage(), getImage(), getImage(), getImage(), getImage(), getImage(), getImage(), getImage(), getImage(), getImage(), getImage(), getImage(), ]); const data = await Promise.all(res.forEach((r) => r.blob())); console.log(data); data.forEach((d) => { const img = document.createElement("img"); img.src = URL.createObjectURL(d); container.append(img); }); } catch { (err) => console.error(`${err.message}`); } }; firstImages();
问题分析与修正
1. getImage函数未返回Promise
原并发代码里的getImage只执行了fetch但没有返回它的Promise,导致Promise.all接收的是15个undefined,后续所有基于res的操作都无效。需要给getImage加上return:
const getImage = function () { // 加上return返回fetch的Promise return fetch("https://api.api-ninjas.com/v1/randomimage", { method: "GET", headers: { "X-API-Key": "###", Accept: "image/jpg", }, }); };
2. forEach无法生成Promise数组给Promise.all
res.forEach((r) => r.blob())不会返回任何值(forEach返回undefined),Promise.all需要接收一个Promise数组,应该改用map:
// 把forEach改成map,生成包含blob Promise的数组 const data = await Promise.all(res.map((r) => r.blob()));
3. catch块语法错误
原代码的catch写法是catch { (err) => ... },这是语法错误,正确的错误捕获应该是catch(err) => ...或者catch(err) { ... },否则错误无法被捕获到:
catch (err) { console.error(`${err.message}`); }
修正后的完整并发代码
const getImage = function () { return fetch("https://api.api-ninjas.com/v1/randomimage", { method: "GET", headers: { "X-API-Key": "###", Accept: "image/jpg", }, }); }; const firstImages = async function () { try { // 用Array.from简化15次调用的写法 const resList = await Promise.all(Array.from({length:15}, getImage)); const blobList = await Promise.all(resList.map(res => { if (!res.ok) throw new Error(`Network failure! Status: ${res.status}`); return res.blob(); })); blobList.forEach(blob => { const img = document.createElement("img"); img.src = URL.createObjectURL(blob); container.append(img); }); } catch (err) { console.error(`${err.message}`); } }; firstImages();
内容的提问来源于stack exchange,提问作者RK3110
相关产品推荐
相关产品推荐

