You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Flask实现Server-Sent Events(SSE)时浏览器直接显示原始事件数据而非渲染HTML页面的问题求助

Flask实现Server-Sent Events(SSE)时浏览器直接显示原始事件数据而非渲染HTML页面的问题求助

我正在尝试用SSE自动更新我Web应用中嵌入的图片源。虽然我已经用Python和Flask创建了应用里的好几个页面,但我对SSE完全是新手,现在正试着基于一个示例让它跑起来。

现在输出和预期完全不符:浏览器没有显示正常的网页、逐句展示内容,反而直接显示了for循环里yield语句生成的原始字符串,连data:前缀和双换行都原样显示出来了。我访问的是127.0.0.1/events这个地址,效果如下:

浏览器显示原始SSE数据的截图

我把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

火山引擎 最新活动