Flask服务器在客户端发送事件(SSE)流数据错误

2024-05-04 23:17:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道如何创建一个web应用程序来帮助人们完成需要多个参与者同时在线的过程。 例如,我们有一个程序A,需要3个人,包含以下步骤:

  1. 第1步-要求1号人员
  2. 第2步-要求2号人员
  3. 第1步-要求1号人员
  4. 第1步-要求3号人员
  5. 第1步-要求3号人员
  6. 第1步-要求1号人员 等等

从动作发生到它将显示在其他参与者屏幕上的时间应该很短——大约1-2秒

在这里,使用轮询更新应用程序状态似乎不是一个好主意,所以我查看了服务器发送事件(SSE)

我用React和烧瓶写了一个小测试。代码如下:

server.py

from flask import Flask, Response
from queue import Queue
import json
from waitress import serve
from flask_cors import CORS

# The queue stores the updated states.
# Here we have only one queue but every participant should have it's own queue
q=Queue()

app = Flask(__name__)
CORS(app, supports_credentials=True)

# This represents the shared state
buttons = {
    "btn1":False,
    "btn2":False,
    "btn3":False
}

# The stream
@app.route("/listen")
def listen():
        global q
        while True:
            if not q.empty():
                data = q.get()
                json_data = json.dumps(data) 
                formatted_data = f"id:1\ndata:{json_data}\nevent: online\n\n"
                return Response(formatted_data, mimetype='text/event-stream') 

# Here the changes are recieved and handled
# Every change is updated in the shared state
# Shared state is then pushed to the queue
# Probably should only send the changes in state and not the whole state
# But this is good enough for the test
@app.route("/btn/<int:btnNumber>",methods=["POST",'GET'])
def changeButton(btnNumber):
    global buttons
    global q
    buttons['btn'+str(btnNumber)] = not buttons['btn'+str(btnNumber)]
    q.put(buttons)
    return 'done'

# Waitress serves the application
if __name__ == "__main__":
    serve(app, host='0.0.0.0', port=5000)

客户端App.js组件:

import './App.css';
import {useState} from 'react';
import axios from 'axios';


var source = new EventSource('http://127.0.0.1:5000/listen');
  source.onopen = function() {
      console.log('connection to stream has been opened');
  };
  source.onerror = function (error) {
      console.log('An error has occurred while receiving stream', error);
  };
  source.onmessage = function (stream) {
      console.log('received stream', stream);
  };
  
function App() {

  const [state, setState] = useState({
                                    btn1: false,
                                    btn2: false,
                                    btn3: false,
                                      });

  
  const buttonClickedHandler = btnNumber => {
      axios.post('http://127.0.0.1:5000/btn/'+btnNumber).then(resp=>console.log(resp))
  }
  return (
    <div className="App">
      {Object.entries(state).map(([k,v])=><button 
                                            key={k}
                                            onClick={()=>buttonClickedHandler(k[k.length-1])} 
                                            className={v?"GREEN":"RED"}>
                                          </button>
                                  )}
    </div>
  );
}

export default App;

App.css

.App {
    display: flex;
    width: 100%;
    height: 100%;
    justify-content: center;
    align-items: center;
}

.RED {
    background-color: red;
}

.GREEN {
    background-color: green;
}

button {
    width: 100px;
    height: 50px;
    margin: 16px;
}

在运行服务器和客户端后,我单击其中一个按钮并获得以下信息: SSE Error

我现在试图理解为什么我会出现这个错误? 响应数据的结构/格式是否不正确

我使用我在这个youtube video中找到的示例来决定返回的数据应该是什么样子(签出9:25查看代码)

另外,在视频中,我注意到它返回一个gregenerator。我想这不是我需要的,因为我没有大量的数据要发送,并且在队列更新时需要更新——不是每秒钟更新一次

请用这个箱子引导我-谢谢