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

使用Fetch API的GET请求结合forEach循环无法批量获取API数据

解决React类组件中批量API请求导致的资源耗尽问题

我来帮你分析下问题所在,并用基础React类组件语法给出解决方案:

问题根源拆解

  1. 在render中调用getPlants()是致命错误
    React的render方法会在组件状态/ props变化、父组件渲染等多种场景下重复执行。你每次渲染都循环发起大量API请求,瞬间占用浏览器的网络资源,直接导致net::ERR_INSUFFICIENT_RESOURCES错误。

  2. 未控制API请求并发量
    直接用forEach一次性发起所有请求,会超出浏览器的并发连接限制(一般浏览器同时最多允许6-8个同域名请求),大量请求排队等待会耗尽系统资源。

  3. 全局datas变量不符合React状态管理逻辑
    你直接用未初始化的全局数组存储结果,既无法触发组件重新渲染展示数据,也容易导致数据混乱。


基础React类组件解决方案

下面是修改后的完整代码,我会逐点说明关键改进:

class YourComponent extends React.Component {
  state = { 
    items: [], 
    plants: [] 
  };

  componentDidMount() {
    // 第一步:先获取组织数据
    fetch('https://cors-anywhere.herokuapp.com/https://seffaflik.epias.com.tr/transparency/service/production/dpp-organization', {
      method: "GET",
      headers: { 
        "Content-Type": "application/json", 
        'X-Requested-With': 'XMLHttpRequest' 
      }
    })
    .then(response => response.json())
    .then(resultJson => {
      this.setState(
        { items: resultJson.body.organizations },
        // 关键:组织数据获取完成后,再调用getPlants,而不是在render里
        this.getPlants
      );
    })
    .catch(err => console.error('获取组织数据失败:', err));
  }

  getPlants = () => {
    const { items } = this.state;
    if (items.length === 0) return;

    // 1. 把每个请求包装成Promise
    const requestPromises = items.map(plant => {
      return fetch(`https://cors-anywhere.herokuapp.com/https://seffaflik.epias.com.tr/transparency/service/production/dpp-injection-unit-name?organizationEIC=${plant.organizationETSOCode}`, {
        method: 'GET',
        headers: { 
          "Content-Type": "application/json", 
          'X-Requested-With': 'XMLHttpRequest' 
        }
      })
      .then(response => {
        if (!response.ok) throw new Error(`请求失败: ${response.status}`);
        return response.json();
      })
      .then(resultJson => resultJson.body.injectionUnitNames)
      .catch(err => {
        console.error(`获取plant ${plant.organizationETSOCode}数据失败:`, err);
        return []; // 出错时返回空数组,避免Promise.all失败
      });
    });

    // 2. 用Promise.all批量处理请求,同时可以考虑分批优化(可选)
    Promise.all(requestPromises)
    .then(allPlantsData => {
      // 合并所有请求结果,更新组件状态
      this.setState(prevState => ({
        plants: [...prevState.plants, ...allPlantsData.flat()]
      }));
    })
    .catch(err => console.error('批量获取plants数据失败:', err));
  };

  render() {
    const { plants } = this.state;
    return (
      <div>
        {/* 在这里渲染plants数据,比如: */}
        {plants.length > 0 ? (
          <ul>
            {plants.map((plant, index) => (
              <li key={index}>{plant.name}</li>
            ))}
          </ul>
        ) : (
          <p>加载中...</p>
        )}
      </div>
    );
  }
}

关键改进说明

  • 把getPlants移到componentDidMount的回调中:确保只有组织数据成功获取后,才发起后续请求,避免无效请求,也不会在render中重复触发。
  • 用Promise.all管理批量请求:既可以统一处理所有请求的结果,也能保证代码的可读性;如果请求数量特别多,可以进一步改成分批请求(比如每次只发5个请求,完成一批再发下一批)。
  • 用组件状态plants存储结果:替代全局datas,通过setState触发组件重新渲染,展示最新数据。
  • 增加错误处理:每个请求都添加catch,避免单个请求失败导致整个批量请求崩溃,同时方便排查问题。

可选优化:限制并发请求数量

如果items的数量非常大(比如几十上百个),Promise.all一次性发起所有请求还是可能触发资源问题,这时候可以实现一个简单的并发限制函数:

// 工具函数:限制并发请求数量
const fetchWithConcurrency = (promises, limit) => {
  let index = 0;
  let results = [];
  let activeCount = 0;

  return new Promise((resolve) => {
    const next = () => {
      if (index >= promises.length && activeCount === 0) {
        resolve(results);
        return;
      }

      while (activeCount < limit && index < promises.length) {
        const promise = promises[index];
        const currentIndex = index;
        activeCount++;
        index++;

        promise
        .then(res => {
          results[currentIndex] = res;
        })
        .catch(err => {
          results[currentIndex] = [];
          console.error('请求失败:', err);
        })
        .finally(() => {
          activeCount--;
          next();
        });
      }
    };

    next();
  });
};

// 在getPlants中使用:
getPlants = () => {
  const { items } = this.state;
  if (items.length === 0) return;

  const requestPromises = items.map(plant => {
    // 这里和之前的请求Promise一样
    return fetch(`https://cors-anywhere.herokuapp.com/https://seffaflik.epias.com.tr/transparency/service/production/dpp-injection-unit-name?organizationEIC=${plant.organizationETSOCode}`, {
      method: 'GET',
      headers: { 
        "Content-Type": "application/json", 
        'X-Requested-With': 'XMLHttpRequest' 
      }
    })
    .then(response => {
      if (!response.ok) throw new Error(`请求失败: ${response.status}`);
      return response.json();
    })
    .then(resultJson => resultJson.body.injectionUnitNames)
    .catch(err => {
      console.error(`获取plant ${plant.organizationETSOCode}数据失败:`, err);
      return [];
    });
  });

  // 限制同时最多发起5个请求
  fetchWithConcurrency(requestPromises, 5)
  .then(allPlantsData => {
    this.setState(prevState => ({
      plants: [...prevState.plants, ...allPlantsData.flat()]
    }));
  });
};

这样就能进一步避免一次性占用过多网络资源,彻底解决net::ERR_INSUFFICIENT_RESOURCES错误。

内容的提问来源于stack exchange,提问作者alperenoz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 16:02:46