Flask流响应更新异常求助:无法实时推送内容
问题:Flask流响应无法实时推送到前端
参考相关示例代码测试Flask流响应更新时,出现以下问题:后端Python控制台每秒正常输出Line X,但前端无法实时获取数据,最终一次性接收全部内容。
测试代码
Flask后端代码
from flask import Response, Flask, render_template import time app = Flask(__name__) @app.route('/') def main(): return render_template('index2.html') def generate_text_stream(): for i in range(10): time.sleep(1) print(f"Line {i}\n") yield f"Line {i}\n" @app.route('/stream') def text_stream(): return Response(generate_text_stream(), mimetype='text/plain') app.run(debug=False)
前端HTML代码
<p>This is the latest output: <span id="latest"></span></p> <p>This is all the output:</p> <ul id="output"></ul> <script> var latest = document.getElementById('latest'); var output = document.getElementById('output'); var xhr = new XMLHttpRequest(); xhr.open('GET', '/stream'); xhr.send(); var position = 0; function handleNewData() { console.log(new Date()); var messages = xhr.responseText.split('\n'); console.log(messages); messages.slice(position, -1).forEach(function(value) { latest.textContent = value; var item = document.createElement('li'); item.textContent = value; output.appendChild(item); }); position = messages.length - 1; } var timer; timer = setInterval(function() { handleNewData(); if (xhr.readyState == XMLHttpRequest.DONE) { clearInterval(timer); latest.textContent = 'Done'; } }, 1000); </script>
异常原因
- WSGI服务器输出缓冲:Flask内置的Werkzeug服务器默认会缓冲响应内容,只有缓冲区满或响应结束时才会推送内容到客户端,导致前端无法实时接收。
- 缺少禁用缓冲的响应头:部分反向代理(如Nginx)或浏览器会对流式响应做缓冲处理,未明确禁用时会延迟内容推送。
- 前端轮询的局限性:
setInterval固定间隔检查的方式,无法及时捕获新数据,效率也较低。
修复方法
1. 修改Flask后端,强制刷新并禁用缓冲
在生成流式响应时添加缓冲区刷新操作,同时设置响应头明确禁用各级缓冲:
from flask import Response, Flask, render_template import sys import time app = Flask(__name__) @app.route('/') def main(): return render_template('index2.html') def generate_text_stream(): for i in range(10): time.sleep(1) line = f"Line {i}\n" print(line) yield line # 强制刷新输出缓冲区,确保内容立即发送 sys.stdout.flush() @app.route('/stream') def text_stream(): # 设置响应头禁用各级缓冲 headers = { 'X-Accel-Buffering': 'no', # 禁用反向代理缓冲 'Cache-Control': 'no-cache', # 禁用浏览器缓存 'Transfer-Encoding': 'chunked' # 明确使用分块传输编码 } return Response(generate_text_stream(), mimetype='text/plain; charset=utf-8', headers=headers) app.run(debug=False, threaded=True) # 启用线程支持,避免请求阻塞
2. 优化前端,使用onprogress事件替代轮询
利用XMLHttpRequest的onprogress事件,在收到新数据时立即处理,比轮询更高效及时:
<p>This is the latest output: <span id="latest"></span></p> <p>This is all the output:</p> <ul id="output"></ul> <script> var latest = document.getElementById('latest'); var output = document.getElementById('output'); var position = 0; var xhr = new XMLHttpRequest(); xhr.open('GET', '/stream'); xhr.responseType = 'text'; // 收到新数据时触发处理逻辑 xhr.onprogress = function() { handleNewData(); }; // 请求完成后收尾 xhr.onload = function() { handleNewData(); latest.textContent = 'Done'; }; xhr.send(); function handleNewData() { var messages = xhr.responseText.split('\n'); messages.slice(position, -1).forEach(function(value) { if (value) { // 过滤空行 latest.textContent = value; var item = document.createElement('li'); item.textContent = value; output.appendChild(item); } }); position = messages.length - 1; } </script>
内容的提问来源于stack exchange,提问作者Hansen Zhao
相关产品推荐
相关产品推荐

