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

如何多次请求API?并发调用API失败问题求助

如何安全地多次发起API请求并避免并发问题?

看起来你遇到了并发API请求导致失败的典型问题,而且你的状态更新逻辑也存在一些潜在的坑,我来帮你一步步梳理解决办法:

先说说你当前代码的核心问题

  • 无限制并发请求:用map循环直接发起所有请求,会瞬间创建大量并发HTTP请求。浏览器对同一域名的并发请求数是有限制的(一般是6-8个),而且后端API也可能有并发调用频率的限制,这就会导致部分请求被浏览器或后端拒绝,出现失败的情况。
  • 状态更新的异步问题:你用了一个外部的array变量来收集结果,然后在每个then回调里调用setState。但setState是异步操作,而且多个回调会共享同一个array引用,最终的result状态可能不会准确反映所有符合条件的结果,甚至会出现覆盖的情况。

解决方案一:串行发起请求(最稳妥的低并发方式)

如果你的API没有很高的性能要求,或者后端对并发限制严格,推荐用async/await配合for...of循环来逐个发起请求,这样同一时间只有一个请求在进行:

// 先把方法改成async函数
async fetchEmployees() {
  const { localjson, floor } = this.state;
  let result = [];
  
  for (const item of localjson) {
    const date = this.formatDate(item.date);
    const time = this.formatTime(item.time);
    const id = item.id;
    
    try {
      const response = await axios.get(`http://localhost:3300/api/employees/${id}/${date}/${time}/${floor}`);
      if (response.data === false) {
        // 创建新对象避免修改原数据,加入结果数组
        const modifiedItem = { ...item, date, time };
        result = [...result, modifiedItem];
        // 用函数式setState确保拿到最新状态
        this.setState(prevState => ({ result: [...prevState.result, modifiedItem] }));
      }
    } catch (error) {
      console.error(`请求ID为${id}的员工数据失败:`, error);
      // 可在这里处理失败逻辑,比如重试或记录错误
    }
  }
}

解决方案二:限制并发数(兼顾效率和稳定性)

如果需要一定的并发效率,但又不想超过限制,可以把请求分成批次,比如每次同时发起3个请求,处理完一批再进行下一批:

async fetchEmployees() {
  const { localjson, floor } = this.state;
  const batchSize = 3; // 控制每次并发的请求数
  let result = [];
  
  // 把请求数组拆分成批次
  for (let i = 0; i < localjson.length; i += batchSize) {
    const batch = localjson.slice(i, i + batchSize);
    // 生成当前批次的请求Promise
    const batchPromises = batch.map(async (item) => {
      const date = this.formatDate(item.date);
      const time = this.formatTime(item.time);
      const id = item.id;
      try {
        const response = await axios.get(`http://localhost:3300/api/employees/${id}/${date}/${time}/${floor}`);
        return response.data === false ? { ...item, date, time } : null;
      } catch (error) {
        console.error(`请求ID为${id}的员工数据失败:`, error);
        return null;
      }
    });
    
    // 等待当前批次所有请求完成
    const batchResults = await Promise.all(batchPromises);
    // 过滤无效结果并合并到总结果
    const validResults = batchResults.filter(item => item !== null);
    result = [...result, ...validResults];
    this.setState({ result });
  }
}

额外的优化建议

  • 强制错误处理:一定要加上try/catch或axios的catch回调,避免单个请求失败导致整个流程中断。
  • 保持数据不可变性:不要直接修改原item的属性,用对象展开运算符{...item, date, time}创建新对象,避免污染原数据。
  • 函数式setState优先:当新状态依赖旧状态时,使用this.setState(prevState => {...})的形式,确保拿到最新的状态值,避免异步更新导致的状态不一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:18:27