python - SocketIO 在连续发出时变慢()
问题描述
我正在尝试制作一个简单的脚本来将事件从 python 应用程序推送到客户端。我制作了一个Console
React 组件,它使用 SocketIO 来接收事件,并且我正在使用 Flask SocketIO 推送消息。
这是我的app.py
:
from flask import Flask, request
from flask_socketio import SocketIO, send
app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins='*')
@app.route('/send/<int:n>')
def send_n(n):
for i in range(n):
socketio.emit('console', str(i+1))
socketio.sleep(0.1)
return 'OK'
if __name__ == '__main__':
socketio.run(app)
该函数send_n(n)
只是将n
事件推送到客户端,间隔 0.25 秒。
这是简化 Console
的组件(它重现了不良行为):
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(() => {
props.socket.on('console', msg => {
setMessages([...messages, `${new Date().toLocaleTimeString()} ${msg}`])
})
})
return (
<div className='console' style={{ height: '200px' }}>
<ul>
{messages.map((msg, i) => <li key={i}>{msg}</li>)}
</ul>
</div>
)
}
它通过 props 接收已经连接的套接字。
该组件渲染得很好,直到它有大约 10 个元素,但随后它变慢了,到第 13 行它冻结了,我什至无法关闭选项卡而不必先终止进程。
Flask 的调试器为渲染的每一行注册消息,但未渲染的行(我尝试将 25 作为值n
)似乎从未发送过。
所以我有两个问题:
- 为什么烧瓶不发送每条消息?某种糟糕的排队?
- 为什么后端套接字冻结时反应冻结?
此外,如果我制作msg
时间戳,第一条消息会很快呈现,但后端时间戳和 React 时间戳之间的差异会随着消息数量的增加而迅速增长。
解决方案
我按照@Miguel 的评论解决了它。
长话短说,该useEffect()
函数在每次渲染时都会执行,并且每次执行时都会添加一个新的处理程序,而不会删除前一个处理程序,因此在几次渲染之后,事情就会以指数方式失控。所以我只是添加了一行来在处理程序完成时删除它。
useEffect(():any => {
props.socket.on('console', msg => {
setMessages([...messages, `${new Date().toLocaleTimeString()} ${msg}`])
})
return () => props.socket.off('console')
})
现在它的渲染没有问题。
推荐阅读
- r - missForest 不会估算我的分类变量
- python - 获取许可证 OpenCV 项目时出错
- r - 安装软件包而不先重新启动 R 的影响?
- android - Viewmodel 在完成活动后保留数据
- metal - 我无法在手机中运行任何金属计算着色器
- php - 从 xampp 访问 phpmyadmin 时访问被拒绝错误
- javascript - 与角度一起使用时,p5.js 中的变量未定义?
- google-chrome - 有没有办法在 Chrome 上立即显示标签工具提示?
- html - Bootstrap 导航栏不能用作粘性导航栏,我如何使它工作
- php - 基于 WP_Customize 更改 Wordpress 模板 CSS