Javascript 更新时显示烧瓶视图中的数据流
我有一个视图,可以实时生成数据并将其流式传输。我不知道如何将此数据发送到可以在HTML模板中使用的变量。我当前的解决方案只是在数据到达时将其输出到一个空白页面,这是可行的,但我希望将其包含在一个带有格式的较大页面中。如何在数据流传输到页面时更新、格式化和显示数据Javascript 更新时显示烧瓶视图中的数据流,javascript,python,flask,stream,Javascript,Python,Flask,Stream,我有一个视图,可以实时生成数据并将其流式传输。我不知道如何将此数据发送到可以在HTML模板中使用的变量。我当前的解决方案只是在数据到达时将其输出到一个空白页面,这是可行的,但我希望将其包含在一个带有格式的较大页面中。如何在数据流传输到页面时更新、格式化和显示数据 import flask import time, math app = flask.Flask(__name__) @app.route('/') def index(): def inner(): # s
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)
导入烧瓶
输入时间、数学
app=烧瓶。烧瓶(\uuuuu名称\uuuuuuu)
@应用程序路径(“/”)
def index():
def inner():
#模拟要观看的长过程
对于范围(500)内的i:
j=数学sqrt(i)
时间。睡眠(1)
#此值应插入到HTML模板中
收益率str(i)+'
\n'
return flask.Response(inner(),mimetype='text/html')
app.run(debug=True)
您可以在响应中流式传输数据,但不能按照您描述的方式动态更新模板。模板在服务器端呈现一次,然后发送到客户端
一种解决方案是使用JavaScript读取流式响应并在客户端输出数据。使用XMLHttpRequest
向将流式传输数据的端点发出请求。然后定期从流中读取数据,直到完成为止
这引入了复杂性,但允许直接更新页面,并提供对输出外观的完全控制。下面的示例通过显示当前值和所有值的日志来演示这一点
本例假设一种非常简单的消息格式:一行数据,后跟一个换行符。这可以根据需要变得复杂,只要有一种方法来识别每条消息。例如,每个循环都可以返回一个JSON对象,由客户机解码
从数学导入sqrt
从时间上导入睡眠
从烧瓶导入烧瓶,渲染\u模板
app=烧瓶(名称)
@附件路线(“/”)
def index():
返回渲染模板(“index.html”)
@应用程序路径(“/stream”)
def stream():
def generate():
对于范围(500)内的i:
产生“{}\n”。格式(sqrt(i))
睡眠(1)
返回app.response_类(generate(),mimetype=“text/plain”)
这是最新的输出:
这是所有的输出:
var latest=document.getElementById('latest');
var output=document.getElementById('output');
var xhr=new XMLHttpRequest();
open('GET','url_for('stream')});
xhr.send();
var位置=0;
函数handleNewData(){
//响应文本包括到目前为止的整个响应
//拆分消息,然后获取尚未处理的消息
//位置跟踪已处理的邮件数
//消息以换行符结尾,因此split将始终在末尾显示一条额外的空消息
var messages=xhr.responseText.split('\n');
messages.slice(位置,-1).forEach(函数(值){
latest.textContent=value;//就地更新最新值
//生成一个新项并将其附加到列表以记录所有输出
var item=document.createElement('li');
item.textContent=值;
输出。追加子项(项);
});
位置=消息长度-1;
}
无功定时器;
计时器=设置间隔(函数(){
//检查新数据的响应
handleNewData();
//响应结束后停止检查
if(xhr.readyState==XMLHttpRequest.DONE){
清除间隔(计时器);
latest.textContent='Done';
}
}, 1000);
可以用来显示流式HTML输出,但它有一些缺点。框架是一个单独的文档,它增加了资源的使用。因为它只显示流数据,所以可能不容易像页面的其余部分那样设置样式。它只能附加数据,所以长时间输出将呈现在可见滚动区域下方。它无法修改页面的其他部分以响应每个事件
index.html
使用指向流
端点的框架呈现页面。框架具有相当小的默认尺寸,因此您可能需要进一步设置其样式。使用知道转义变量的render\u template\u string
,为每个项目呈现HTML(或者使用render\u template
和更复杂的模板文件)。可以产生一个初始行,首先在帧中加载CSS
从flask导入渲染模板字符串,使用上下文流
@应用程序路径(“/stream”)
def stream():
@流_与_上下文
def generate():
生成渲染模板字符串(“”)
对于范围(500)内的i:
产生呈现模板字符串(“{{i}}:{{{s}}\n”,i=i,s=sqrt(i))
睡眠(1)
返回app.response_类(generate())
这是所有的输出:
5年后,但这实际上可以按照您最初尝试的方式完成,javascript完全没有必要(编辑:在我写这篇文章之后,接受答案的作者添加了iframe部分)。您只需将嵌入输出作为
:
从烧瓶导入烧瓶,呈现模板,响应
输入时间、数学
app=烧瓶(名称)
@app.route(“/content”)#将内容呈现为与索引不同的url
def content():
def inner():
#模拟要观看的长过程
对于范围(500)内的i:
j=数学sqrt(i)
时间。睡眠(1)
#此值应插入到HTML模板中
收益率str(i)+'
\n'
返回响应(内部(),mimetype='text/html')
@应用程序路径(“/”)
def index():
返回render_template('index.html.jinja')#在索引处呈现模板。内容将嵌入此模板中
app.run(debug=True)
然后,“index.html.jinja”文件将包含一个
,其中的内容url作为src,这可能会
<!doctype html>
<head>
<title>Title</title>
</head>
<body>
<div>
<iframe frameborder="0" noresize="noresize"
style='background: transparent; width: 100%; height:100%;' src="{{ url_for('content')}}"></iframe>
</div>
</body>