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

如何阻止fetch发起多余请求?React+Flask Socket.IO场景

解决Socket.IO事件触发多次Fetch请求的问题

问题根源

你当前的代码在组件每次渲染时都会重复绑定socket.on("upload_finished")事件监听器,导致同一个事件触发后,多个回调实例都会执行——哪怕用了useState控制,初始状态下所有回调都能通过allowParse === true的判断,自然会发起多次请求。

解决方案

方案1:用useEffect绑定+useRef控制执行

把事件监听器绑定放到useEffect里,确保只绑定一次,同时用useRef替代useState来控制是否执行请求,避免状态更新的异步问题:

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

// 组件内部代码
const hasFetched = useRef(false);

useEffect(() => {
  const handleUploadFinished = (response) => {
    if (!hasFetched.current) {
      console.log("parse start");
      fetch("start-parse", { method: "POST" });
      hasFetched.current = true;
    }
  };

  // 绑定事件监听器
  socket.on("upload_finished", handleUploadFinished);

  // 组件卸载时移除监听器,防止内存泄漏
  return () => {
    socket.off("upload_finished", handleUploadFinished);
  };
}, []); // 空依赖数组,仅组件挂载时执行一次

useRef的current值不会触发组件重渲染,且在组件生命周期内保持稳定,能精准控制请求只执行一次;useEffect空依赖确保监听器只绑定一次,避免重复绑定。

方案2:用socket.once监听单次事件

如果这个upload_finished事件只需要响应一次,直接用socket.once替代socket.on,它会在事件触发一次后自动解绑监听器:

import { useEffect } from 'react';

// 组件内部代码
useEffect(() => {
  socket.once("upload_finished", (response) => {
    console.log("parse start");
    fetch("start-parse", { method: "POST" });
  });

  // 组件提前卸载时清理监听器(可选,但更安全)
  return () => {
    socket.off("upload_finished");
  };
}, []);

额外排查点

  • 检查后端upload_file函数是否被多次调用:如果Flask接口重复触发socketio.emit("upload_finished"),前端自然会收到多次事件。
  • 确认组件是否重复挂载:如果组件被频繁重渲染/挂载,也会导致监听器重复绑定,可以用React.memo包裹组件,减少不必要的重渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:22:16