Flask实现Server-Sent Events(SSE)时浏览器直接显示原始事件数据而非渲染HTML页面的问题求助
我正在尝试用SSE自动更新我Web应用中嵌入的图片源。虽然我已经用Python和Flask创建了应用里的好几个页面,但我对SSE完全是新手,现在正试着基于一个示例让它跑起来。
现在输出和预期完全不符:浏览器没有显示正常的网页、逐句展示内容,反而直接显示了for循环里yield语句生成的原始字符串,连data:前缀和双换行都原样显示出来了。我访问的是127.0.0.1/events这个地址,效果如下:

我把Python代码放在了名为SSE_tester.py的文件里,代码如下:
from flask import Flask, Response app = Flask(__name__) @app.route('/events') def sse_handler(): def generate(): paragraph = [ "Hello, this is an example of a continuous text output.", "It contains multiple sentences, each of which will be sent to the client as an event.", "This is to simulate the functionality of Server-Sent Events (SSE).", "We can use this method to push real-time updates.", "End of sample text, thank you!", ] for sentence in paragraph: yield f"data: {sentence}\n\n" import time time.sleep(1) return Response(generate(), mimetype='text/event-stream') if __name__ == '__main__': app.run(host='0.0.0.0', port=8081, debug=True)
我在这段代码里没看到哪里指定了浏览器API的位置(可能app.route算?)。我对JavaScript一窍不通,很可能作者默认读者知道一些我不懂的JS操作,要是这样的话,还请大家教教我这部分怎么做。
示例里还包含了浏览器端的API代码,我把它复制过来放在下面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SSE Example </title> </head> <body> <h1>Server-Sent Events Example </h1> <div id="messages"></div> <script> window.onload = function() { if (typeof(EventSource)!== "undefined") { const eventSource = new EventSource('/events'); eventSource.onmessage = function(event) { const newElement = document.createElement("p"); newElement.textContent = "Message: " + event.data; document.getElementById("messages").appendChild(newElement); }; eventSource.onerror = function(event) { console.error("Error occurred: ", event); const newElement = document.createElement("p"); newElement.textContent = "An error occurred while connecting to the event source."; document.getElementById("messages").appendChild(newElement); eventSource.close(); }; } else { document.getElementById("messages").textContent = "Sorry, your browser does not support server-sent events..."; } }; </script> </body> </html>
这段代码里包含HTML内容,所以我把它存成了events.html文件,放在了名为events的子目录里(对应app.route的路径)。
按我对这段HTML的理解,页面至少应该显示一个“Server-Sent Events Example”的标题,但实际没有。为了验证HTML文件是不是没起作用,我还临时删掉了它,结果还是一样,显然这个文件被忽略了。我的文件路径如下:

我试过把HTML文件名改成index.html,也没用。而且全程没有任何错误提示。
所以我到底哪里做错了?为什么浏览器和Python脚本都忽略了浏览器端的API代码?我觉得如果连这个示例都跑不起来,那我自己应用里的SSE功能肯定也搞不定。
补充一下我的环境信息:我们公司是纯Windows环境,所以依赖Linux的方案可能帮不上忙。浏览器是Chrome 134.0.6998.36(Windows 10 Enterprise系统),Python版本3.9.13(在Wing Pro IDE中运行),Flask版本1.1.2。
一开始我以为这和某个Stack Overflow问题的情况类似(那个问题是ChatGPT生成的随机标签导致HTML无法渲染),但我测试的代码里没有这类问题,而且我用Flask创建的其他页面都能正常渲染,所以应该不是同一个问题。另外我只需要单向通信,用WebSocket可能有点大材小用了。
非常感谢各位的解答!
备注:内容来源于stack exchange,提问作者Patrick R




