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

Flask SocketIO连续调用emit变慢及React前端卡顿问题咨询

问题1:前端页面冻结的原因

你当前的React代码存在两个致命问题:

  • 首先useEffect没有传入第二个依赖数组参数,这会导致每次组件渲染时都会重新绑定一次socket的console事件监听器。第一次收到消息触发重渲染,监听器数量变成2;第二次收到消息两个监听器同时触发,触发两次重渲染,监听器数量变成4,以此类推指数级增长,十几条消息后监听器数量就会涨到成千上万,直接占满浏览器主线程导致页面冻结。
  • 其次你调用setMessages时用的是闭包捕获的旧messages数组,不是最新的状态,会出现状态更新被覆盖的异常。

修复后的React组件代码如下:

import { useState, useEffect } from 'react'
import '../styles/console.css'
import { Socket } from 'socket.io-client'

interface ConsoleProps {
    socket: Socket
}

export default function Console(props: ConsoleProps) {
    const [messages, setMessages] = useState<string[]>([])

    useEffect(() => {
        // 定义事件处理函数
        const handleConsole = (msg: string) => {
            // 用函数式更新拿到最新的messages状态
            setMessages(prev => [...prev, `${new Date().toLocaleTimeString()} ${msg}`])
        }
        // 绑定事件
        props.socket.on('console', handleConsole)
        // 返回清理函数,组件卸载/依赖变化时移除事件监听器
        return () => {
            props.socket.off('console', handleConsole)
        }
    }, [props.socket]) // 仅当socket实例变化时重新执行effect

    return (
        <div className='console' style={{ height: '200px' }}>
            <ul>
                {messages.map((msg, i) => <li key={i}>{msg}</li>)}
            </ul>
        </div>
    )
}

问题2:Flask看起来没发完所有消息的原因

这不是Flask的队列配置问题,是SocketIO的背压机制:当客户端主线程被占满无法处理收到的消息时,会停止向服务端发送消息确认包,服务端的SocketIO实例检测到客户端接收不过来,就会把后续要发送的消息暂存在队列里暂停发送,看起来就像消息没有发出去。你修复前端问题后这个现象会自动消失。

如果需要实现仅把消息推送给触发/send/<n>请求的用户,可优化Flask代码如下:

from flask import Flask, request
from flask_socketio import SocketIO, send

app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins='*')

# 连接时记录用户对应的sid
@socketio.on('connect')
def handle_connect():
    # 示例仅存在全局变量演示,生产环境可绑定到用户身份存储
    global current_sid
    current_sid = request.sid

@app.route('/send/<int:n>')
def send_n(n):
    for i in range(n):
        # 指定发送给对应客户端,避免广播给所有连接用户
        socketio.emit('console', str(i+1), to=current_sid)
        socketio.sleep(0.1)
    return 'OK'


if __name__ == '__main__':
    socketio.run(app)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 18:06:03