显示更新时从Flask视图stream式传输的数据

我有一个生成数据并实时stream的视图。 我不知道如何将这些数据发送到我可以在我的HTML模板中使用的variables。 我目前的解决scheme只是输出数据到一个空白页面到达,这是有效的,但我想包括在一个更大的页面格式。 数据stream式传输到页面时,如何更新,格式化和显示数据?

import flask import time, math app = flask.Flask(__name__) @app.route('/') def index(): def inner(): # simulate a long process to watch for i in range(500): j = math.sqrt(i) time.sleep(1) # this value should be inserted into an HTML template yield str(i) + '<br/>\n' return flask.Response(inner(), mimetype='text/html') app.run(debug=True) 

您可以在响应中传输数据,但不能按照您描述的方式dynamic更新模板。 模板在服务器端渲染一次,然后发送到客户端。 您需要使用JavaScript来读取stream式响应,并在客户端输出数据。

使用XMLHttpRequest向将传输数据的端点发出请求。 然后定期从stream中读取,直到完成。

这个例子假定一个非常简单的消息格式:一行数据,然后是一个换行符。 只要有一种方法可以识别每条消息,您当然可以在parsing时尽可能复杂。 例如,你可以返回一个JSON对象并在客户端解码它。

 from time import sleep from flask import Flask, render_template from math import sqrt app = Flask(__name__) @app.route('/') def index(): # render the template (below) that will use JavaScript to read the stream return render_template('index.html') @app.route('/stream_sqrt') def stream(): def generate(): for i in range(500): yield '{}\n'.format(sqrt(i)) sleep(1) return app.response_class(generate(), mimetype='text/plain') app.run() 
 <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', '{{ url_for('stream') }}'); xhr.send(); var position = 0; function handleNewData() { // the response text include the entire response so far // split the messages, then take the messages that haven't been handled yet // position tracks how many messages have been handled // messages end with a newline, so split will always show one extra empty message at the end var messages = xhr.responseText.split('\n'); messages.slice(position, -1).forEach(function(value) { latest.textContent = value; // update the latest value in place // build and append a new item to a list to log all output var item = document.createElement('li'); item.textContent = value; output.appendChild(item); }); position = messages.length - 1; } var timer; timer = setInterval(function() { // check the response for new data handleNewData(); // stop checking once the response has ended if (xhr.readyState == XMLHttpRequest.DONE) { clearInterval(timer); latest.textContent = 'Done'; } }, 1000); </script>