Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask: stream to jQuery/$.post() from generator with yield

Tags:

json

jquery

flask

I would like to stream chunks of data from a generator in flask after I called the function with jQuery $.post():

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

I call this function from jQuery:

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

This only gives me one alert saying 'result1result2' and not two separate alerts for each yield. So the callback function is called after everything was 'yielded'.

How can I properly stream to jQuery with yield?

like image 636
Martin Preusse Avatar asked Jun 18 '13 20:06

Martin Preusse


1 Answers

You can use server-sent events in this case. Check out the sample below:

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()

Server sent events block your development server. To handle multiple connections look into using Gevent. http://flask.pocoo.org/docs/deploying/others/#gevent

like image 59
Teisman Avatar answered Sep 23 '22 23:09

Teisman