You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 11:37:53