React 应用程序未刷新通过 socket.io 流式传输的日志

React app not refreshing the log streamed through socket.io

在我的项目中,我使用 flask_socketio 作为服务器,使用 socket.io-client 作为客户端。我的 main.py(烧瓶服务器)不断读取不断更新的日志文件(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;

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

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

在你的 flask 代码中,如果你想连续流式传输,则需要在循环中调用 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})