Vincentius Kevin
Vincentius Kevin

Reputation: 379

EventSource.onmessage is not firing even though Flask server push seems to work

I created a route /stream which should push the string 'test' every second.

When I open this URL (localhost:12346/stream) on Chrome, it indeed opens a blank page and a "test" is appended to the page every second, so I think the server side is working correctly. When I opened it on Firefox, it treats it as a file download that never finishes.

But when I open client.html below, the onmessage event of the EventSource object is never fired so I get no data. The onopen event was fired and I see it in the console. Why is this? How can I receive the data in the JavaScript side?

server.py:

import flask
import flask_cors
import time

app = flask.Flask(__name__)
app.debug = True
flask_cors.CORS(app)

def event_stream():
    while True:
        time.sleep(1)
        yield 'test\n'

@app.route('/stream')
def stream():
    return flask.Response(event_stream(), mimetype='text/event-stream')

app.run(port=12346, threaded=True)

client.html:

<!DOCTYPE html>
<html>
  <body>
    <script>
        var source = new EventSource('http://localhost:12346/stream');
        source.onopen = e => console.log('opened', event);
        source.onerror = e => console.log('error', event);
        source.onmessage = e => console.log('onmessage', event);
    </script>
  </body>
</html>

Upvotes: 1

Views: 4845

Answers (3)

Hababa
Hababa

Reputation: 571

Though it was later for years.. I faced the same problem with you (message appended to the page but not fired to EventStream)

After search so much examples & test for hours I found some key

You need to yield message with data: prefix and \n suffix, like data:test\n\n

So this should work for you.

def event_stream():
    while True:
        time.sleep(1)
        yield 'data:test\n\n'

And you can see the EventStream with Type=message, Data=test in Chrome Debug Tools (as also source.onmessage)

I think it has another key word like data:, but I didn't find out the document about this, maybe someone can supplement.

Upvotes: 6

chelvan chelvam
chelvan chelvam

Reputation: 11

you can avoid this problem by add @cross_origin() in your code.

import flask
from flask_cors import cross_origin
import time

app = flask.Flask(__name__)

@app.route('/stream')
@cross_origin()
def stream():
    def event_stream():
        while True:
            yield "data:" + "test" + "\n\n"
            time.sleep(1)

    return flask.Response(event_stream(), mimetype='text/event-stream')

app.run(port=12346)

This is the html file

<html>
  <head>
  </head>
  <body>

    <script>

    var source = new EventSource('http://127.0.0.1:12346/stream');
    console.log(source)
    source.onmessage = function(event) {
        console.log(event.data);        
    }

    </script>

  </body>

</html>

Upvotes: 1

Kwiat
Kwiat

Reputation: 31

Server sent event EventStream does not trigger "onmessage" but Chrome Debug shows data in "EventStream" tab

That resolved my problem, backend was sending events with custom type which not triggers onmessage callback

Upvotes: 3

Related Questions