实时更新烧瓶中的数据流。

问题描述 投票:0回答:1

我正试图使用flask和JavaScript将产生的值实时流式传输到HTML中,我想在flask中产生值后立即流式传输并无延迟地显示。然而,我目前还不能在HTML端显示数据。

这是Python Flask的代码。

from flask import Flask, render_template
import time

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/stream_time')
def stream():
    def generate():
        t=time.time()
        yield '{}\n'.format(time)
    return app.response_class(generate(), mimetype='text/plain')

app.run

HTMLJS代码用来实时显示和更新值。

<p>This is the current value: <span id="latest_value"></span></p>
<script>
    var latest = document.getElementById('latest_value');

    var xhr = new XMLHttpRequest();
    xhr.open('GET', '{{ url_for('stream') }}');
    xhr.send();

    var message = xhr.responseText.split('\n');
    latest.textContent = message;
</script>

目前,我没有得到任何显示在页面上的值,我希望这能在字段上实时更新。我做错了什么,如何解决这个问题?

javascript python flask
1个回答
2
投票

JavaScript是异步工作的,在运行send()之后,它不会等待响应,而是在得到带有文本的响应之前执行下一行。

为了得到一个响应,你必须使用 xhr.onload (之前 send())来定义函数,其中 xhr 得到回应后就会运行

 xhr.onload = function () {
    latest.textContent = xhr.responseText;
 }

 xhr.send()

最低限度的工作代码

from flask import Flask, render_template_string
import time

app = Flask(__name__)

@app.route('/')
def index():
    return render_template_string('''<p>This is the current value: <span id="latest_value"></span></p>
<script>
    var latest = document.getElementById('latest_value');

    var xhr = new XMLHttpRequest();
    xhr.open('GET', '{{ url_for('stream') }}');

    xhr.onload = function() {
        latest.textContent = xhr.responseText;
    }

    xhr.send();

    /* this lines will give `><` because `xhr.responseText` is still empty */
    /* you can remove these lines */
    console.log(">" + xhr.responseText + "<")
    latest.textContent = ">" + xhr.responseText + "<";

</script>''')

@app.route('/stream_time')
def stream():
    def generate():
        current_time = time.strftime("%H:%M:%S\n")
        print(current_time)
        yield current_time

    return app.response_class(generate(), mimetype='text/plain')

app.run()

要定期更新浏览器中的文本,您必须先使用 while 循环来发送许多值。

为了测试,我还使用了 time.sleep(1) 以减少数据发送量

    def generate():
        while True:
            current_time = time.strftime("%H:%M:%S\n")
            print(current_time)
            yield current_time
            time.sleep(1)

现在在JavaScript中,你必须使用 xhr.onreadystatechange 分配功能,当服务器有新数据时,该功能将更新页面上的文字。

xhr.onreadystatechange = function() {
    var all_messages = xhr.responseText.split('\n');
    last_message = all_messages.length - 2
    latest.textContent = all_messages[last_message]
}

因为 xhr.responseText 最后以 \n 所以 split('\n') 创建空信息作为列表的最后一个元素 all_messages 所以我用 length - 2 而不是 length - 1


最低限度的工作代码

from flask import Flask, render_template_string
import time

app = Flask(__name__)

@app.route('/')
def index():
    return render_template_string('''<p>This is the current value: <span id="latest_value"></span></p>
<script>

    var latest = document.getElementById('latest_value');

    var xhr = new XMLHttpRequest();
    xhr.open('GET', '{{ url_for('stream') }}');

    xhr.onreadystatechange = function() {
        var all_lines = xhr.responseText.split('\\n');
        last_line = all_lines.length - 2
        latest.textContent = all_lines[last_line]

        if (xhr.readyState == XMLHttpRequest.DONE) {
            /*alert("The End of Stream");*/
            latest.textContent = "The End of Stream"
        }
    }

    xhr.send();

</script>''')

@app.route('/stream_time')
def stream():
    def generate():
        while True:
            current_time = time.strftime("%H:%M:%S\n")
            print(current_time)
            yield current_time
            time.sleep(1)

    return app.response_class(generate(), mimetype='text/plain')

app.run()

另外。 因为我用 render_template_string(html) 而不是 render_template(filename) 所以我不得不使用 \\n 而不是 \n

© www.soinside.com 2019 - 2024. All rights reserved.