7

jQuery $.post() で関数を呼び出した後、フラスコのジェネレーターからデータのチャンクをストリーミングしたいと思います。

@app.route('/some/function', methods=['POST'])
def calculateSomething():
    def g():        
        # do something here
        yield 'result1'
        # do more ...                
        yield 'result2'     
    return Response(g())

jQuery からこの関数を呼び出します。

$.post("/some/function", {"some": $data}, function(data) {
    alert(result)
})

これにより、「result1result2」というアラートが 1 つだけ表示され、利回りごとに 2 つの個別のアラートが表示されることはありません。したがって、コールバック関数は、すべてが「生成」された後に呼び出されます。

yield を使用して jQuery に適切にストリーミングするにはどうすればよいですか?

4

2 に答える 2

8

この場合、サーバー送信イベントを使用できます。以下のサンプルをご覧ください。

from flask import Flask, Response
import time

app = Flask(__name__)

@app.route('/')
def index():
    return """
<!DOCTYPE html>
<html>
  <head>
    <script>
      if(typeof(EventSource)!=="undefined") {
        var source=new EventSource("/stream");
        source.onmessage=function(event) {
          document.getElementById("result").innerHTML+=event.data + "<br>";
        };
      } else {
        document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events...";
      }
    </script>
  </head>
  <body>
    <h1>Data</h1>
    <div id="result"></div>
  </body>
</html>
"""

@app.route('/stream', methods=['GET', 'POST'])
def stream():
    def event_stream():
        n = 0
        while True:
            yield "data: %s\n\n" % n
            n += 1
            time.sleep(1)
    return Response(event_stream(), mimetype='text/event-stream')

if __name__ == '__main__':
    app.run()

サーバー送信イベントは、開発サーバーをブロックします。複数の接続を処理するには、Gevent の使用を検討してください。http://flask.pocoo.org/docs/deploying/others/#gevent

于 2013-06-19T08:47:10.393 に答える
3

これは 1 つの AJAX 要求でありalert、すべてのデータが読み込まれるタイミングを処理します。1 つの request であるため、個別のチャンクを取得することはできませんが、これをエミュレートしてみることができます。

  1. XMLHttpRequest2.progresseventを使用ProgressEvent.loadedして からデータを読み取ってみることができますXMLHttpRequest2.responseが、このイベントがいつ処理されるかは非常に難しい問題です (特に各ブラウザーにとって)。

  2. 試してみることもできますWebRTCが、これにはブラウザーのサポートに制限があり、あなたのケースでは不当に難しいように見えます.

  3. などを忘れないflashでください。

応答が速い場合は、クライアントですべての応答と個別のデータを取得できます (たとえば、blob 構造がわかっている場合は、バイナリ オブジェクトまたは blob に base64 で json を使用できます)。

大きなデータを取得し、実際にチャンクが必要なために応答が長い場合は、新しい接続の時間が大きなチャンクの読み込みよりも短いため、いくつかの要求を行うことをお勧めします。timeoutこの場合、例外をスローする可能性があるため、AJAX に大きなチャンクを使用しないことをお勧めします。

多くの CPU を使用するか、操作が遅いために応答が長い場合は、バックグラウンド プロセス ( などcelery) を開始し、応答を返し、結果を確認した後、間隔を空けてください。

応答を非常に速く取得する必要がある場合は、使用を試すことができますweb sockets(この場合、既に別のメッセージを送信する必要があります)。

したがって、ストリーミングとチャンクが役立つ場合:

  1. 大きなファイルをダウンロードまたはアップロードし、flask アプリケーションで速度を制御したい (ユーザーの引用、この操作にすべてのチャネルを使用しないでください)。ただし、たとえば使用するuwsgiと、この操作の処理時にプロセスまたはスレッドがブロックされます。
  2. 大きなファイルをダウンロードまたはアップロードしていて、この操作を停止/復元/検証したい場合。
于 2013-06-19T08:34:54.753 に答える