【问题标题】:React app not refreshing the log streamed through socket.ioReact 应用程序不刷新通过 socket.io 流式传输的日志
【发布时间】:2021-03-24 18:09:21
【问题描述】:

在我的项目中,我使用 flask_socketio 作为服务器,使用 socket.io-client 作为客户端。我的 main.py(flask server) 不断读取一个不断更新的日志文件(console.log)。当在 UI 中单击开始按钮时,会显示日志文件的数据,但随着我的日志文件更新,更新的数据不会显示在 UI 中。我必须刷新页面或再次单击按钮才能看到更新的数据。 我希望通过单击按钮将日志文件的数据实时流式传输到 UI 上。如何解决这个问题?

烧瓶代码

from flask import Flask, jsonify
# Needed for localhost testing.
from flask_cors import CORS, cross_origin
from flask_socketio import SocketIO, emit
from time import sleep
import pdb
import json

app = Flask(__name__)

# Socket io setup.
app.config['SECRET_KEY'] = 'secret!'
# |cors_allowed_origins| is required for localhost testing.
socket = SocketIO(app, cors_allowed_origins="*")

# For localhost testing.
CORS(app)


@socket.on('event_stream', namespace='/logConsole')
def test_connect():
    def generate():
        fname = "./src/console.log"
        with open(fname) as f:
            yield f.read()
    emit_data = next(generate())
    socket.sleep(0)
    emit('custom-server-msg', {'data': emit_data})


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

反应代码

import React from 'react'
import io from 'socket.io-client'

class App extends React.Component {
state = { startVar: true, setVar: false };

  setSocketListeners() {
    let socket = io.connect('ws://localhost:5000/logConsole');

    socket.emit('event_stream', () => {
      console.log("Websocket connected: " + socket.connected)
    })

    socket.on('custom-server-msg', (data) => {
      console.log("Data received: " + data.data)
      const setup_logs = data.data;
      this.setState({ setup_logs });
    })
  }
  
  render() {
    return (
      <div className="App">
        <h1>Data from log file</h1>
        <button type="button" onClick={() => this.setSocketListeners()}>Start</button>
            <p>{this.state.setup_logs}</p>
      </div>
    );
  }
}

export default App;

这就是我的浏览器控制台的样子-->

这是我的后端控制台-->

【问题讨论】:

  • 当您收到 custom-server-msg 事件时,您是否在浏览器控制台中看到了您的日志语句?
  • @rdrw 是的!我也会添加我的浏览器控制台的屏幕截图。请看一下
  • 对此我不太确定,但custom-server-msg 处理程序的上下文可能与类实例不同,因此没有像预期的那样真正调用setState 并且静默失败。我很好奇您是否将 this 的值记录在发出处理程序中,如果它是 undefined 或当前类组件以外的上下文。

标签: reactjs flask websocket socket.io data-stream


【解决方案1】:

在您的烧瓶代码中,如果您想连续流式传输,则需要在循环中调用 next(),现在可以通过放置一个带有睡眠时间的无限循环来完成,

@socket.on('event_stream')
def test_connect():
    def generate():
        fname = "./src/console.log"
        with open(fname, "r+") as f:
            yield f.read()
    while True:
        emit_data = next(generate())
        socket.sleep(2)
        emit('custom-server-msg', {'data':emit_data})

否则,如果日志文件也在不断更新,可以使用 os.stat(FILE_NAME).st_mtime 来检查正在更新的文件的时间戳,如果日志文件有任何变化,将调用 next() 对其进行流式传输:

@socket.on('event_stream')
def test_connect():
    cached_stamp = 0
    def generate():
        fname = "./src/console.log"
        with open(fname, "r+") as f:
            yield f.read()
    while True:
        stamp = os.stat('./src/console.log').st_mtime
        if stamp != cached_stamp:
            cached_stamp = stamp
            emit_data = next(generate())
            emit('topo-server-msg', {'data':emit_data})

【讨论】:

  • 嗨@Bhavesh!谢谢你这么详细的回答。刚刚试了一下,效果很好。之前我使用transports: ['websocket'] 来停止连续轮询,但它会引发错误。 os.stat(FILE_NAME).st_mtime 解决了我的投票问题。
猜你喜欢
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-07
  • 2018-02-09
  • 2023-04-04
  • 1970-01-01
相关资源
最近更新 更多