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>
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>
Share
Improve this question
edited May 10, 2019 at 13:37
Dylan
2,2193 gold badges31 silver badges52 bronze badges
asked May 10, 2019 at 11:53
Vincentius KevinVincentius Kevin
3796 silver badges17 bronze badges
3 Answers
Reset to default 6Though 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.
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
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>