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

React Hooks实现API1每2秒调用1分钟,解决请求堆积问题

解决方案:避免API轮询时的请求堆积问题

你的核心问题是用setInterval固定间隔触发请求,导致前一次请求pending时仍会发起新请求,最终堆积。解决思路是让下一次请求在前一次请求完成后再延迟2秒发起,而不是固定时间触发。以下是修改后的完整实现:

关键改进点

  • 用状态标记当前是否有请求在进行,防止重复发起
  • 替换setInterval为递归setTimeout,确保请求串行执行
  • 统一处理请求成功/失败的状态重置,避免状态异常
  • 用useRef管理定时器ID,方便清理副作用

修改后的代码

import { useState, useEffect, useRef } from 'react';

const YourComponent = () => {
  const [isPolling, setIsPolling] = useState(false);
  const [isRequestPending, setIsRequestPending] = useState(false);
  const pollTimerRef = useRef(null);
  const startTimeRef = useRef(null); // 用ref保存开始时间,避免状态更新导致的重新渲染问题

  // 核心API调用逻辑
  const callAPI1 = () => {
    if (isRequestPending) return; // 已有请求在进行,直接返回
    setIsRequestPending(true);

    fetch('你的API1地址')
      .then(res => res.json()) // 根据实际接口调整解析逻辑
      .then(data => {
        const conditionMet = /* 替换为你的条件判断,比如data.status === 'completed' */;
        const isTimeout = Date.now() - startTimeRef.current > 60000;

        if (conditionMet || isTimeout) {
          setIsPolling(false);
          if (conditionMet) {
            // 满足条件时调用API2
            fetch('你的API2地址')
              .then(res => res.json())
              .then(api2Data => {
                // 处理API2返回结果
                console.log('API2返回:', api2Data);
              })
              .catch(err => console.error('API2调用失败:', err));
          }
        } else {
          // 前一次请求完成后,延迟2秒发起下一次
          pollTimerRef.current = setTimeout(() => {
            callAPI1();
          }, 2000);
        }
      })
      .catch(err => {
        console.error('API1调用失败:', err);
        // 请求失败后仍继续轮询(可根据需求调整为停止)
        pollTimerRef.current = setTimeout(() => {
          callAPI1();
        }, 2000);
      })
      .finally(() => {
        setIsRequestPending(false); // 请求完成后重置状态
      });
  };

  // 初始请求 + 启动轮询
  const makeFirstCallForAPI1 = () => {
    startTimeRef.current = Date.now();
    callAPI1();
    setIsPolling(true);
  };

  // 点击事件处理
  const onClick = () => {
    if (!isPolling && !isRequestPending) {
      makeFirstCallForAPI1();
    }
  };

  // 组件卸载时清理定时器
  useEffect(() => {
    return () => {
      if (pollTimerRef.current) {
        clearTimeout(pollTimerRef.current);
      }
    };
  }, []);

  return (
    <button onClick={onClick} disabled={isPolling || isRequestPending}>
      {isPolling ? '轮询中...' : '开始轮询'}
    </button>
  );
};

export default YourComponent;

代码说明

  1. 状态与Ref管理:

    • isPolling:标记是否处于轮询状态,用于控制按钮禁用状态
    • isRequestPending:标记当前是否有API1请求在进行,直接阻止重复请求
    • pollTimerRef:保存定时器ID,确保组件卸载时能正确清理
    • startTimeRef:用ref保存轮询开始时间,避免状态更新导致的重新渲染
  2. 轮询逻辑:

    • 初始请求时记录开始时间,之后每次请求完成后,判断是否满足终止条件(超时或符合业务条件)
    • 若未满足终止条件,延迟2秒后发起下一次请求,确保请求串行执行
    • 请求失败时可选择继续轮询或停止,示例中选择继续
  3. 副作用清理:

    • 在组件卸载时清理定时器,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 10:25:22