retry
超时后尝试重新打开连接。这一点曾经让我感到困惑,直到我看到了这篇文章:https://dev59.com/I5ffa4cB1Zd3GeqP6Vj0#38235218
来自链接中的内容:var sse = new EventSource('/sse');
sse.addEventListener('message', function(e) {
console.log(e);
var data = e.data;
if (!data) {
console.log('no data in event');
return;
}
if (data === 'finished') {
console.log('closing connection')
sse.close()
}
// my work here based on message
});
我的Flask服务器
from flask import Response
@app_api.route("/sse")
def stream():
def trackerStream():
finished = check_if_finished()
while not finished:
sleep(1) # poll timeout
if should_send_event():
yield f"data: {mydata()}\n\n"
else:
yield "data: nodata\n\n"
finished = check_if_finished()
yield "data: finished\n\n"
return Response(trackerStream(), mimetype="text/event-stream")
data: nodata\n\n
,服务器也可能陷入循环中。这取决于你的应用程序架构。
让我给你举个例子(请参见此代码:https://github.com/jkbr/chat/blob/master/app.py):
def event_stream():
pubsub = red.pubsub()
pubsub.subscribe('chat')
for message in pubsub.listen():
print message
yield 'data: %s\n\n' % message['data']
@app.route('/stream')
def stream():
return flask.Response(event_stream(),
mimetype="text/event-stream")
Flask稳定地向Redis请求新消息(锁定操作),但当Flask发现流终止时(如果您不是Python的新手,则为 StopIteration
),它会返回。
def event_stream():
pubsub = red.pubsub()
pubsub.subscribe('chat')
for message in pubsub.listen():
if i_should_close_the_connection:
break
yield 'data: %s\n\n' % message['data']
@app.route('/stream')
def stream():
return flask.Response(event_stream(),
mimetype="text/event-stream")
i_should_close_the_connection
是什么?你能再解释一下吗? - hllauif
语句。 - gioipubsub.close()
关闭连接。它“应该”可以工作,但我还没有检查过。 - gioi我曾经遇到同样的问题,最终在这里找到了以下解决方案。
import time
from flask import Flask, Response, stream_with_context
app = Flask(__name__)
@app.route('/stream')
def stream():
def gen():
try:
i = 0
while True:
data = 'this is line {}'.format(i)
print(data)
yield data + '<br>'
i += 1
time.sleep(1)
except GeneratorExit:
print('closed')
return Response(stream_with_context(gen()))
您可以通过向Redis订阅一个监听器来启动该方法。您可以等待Redis的listen()
方法返回值,而不是使用time.sleep(1)
进行等待。您可以取消订阅Redis,而不是使用print('closed')
。唯一剩下的问题是GeneratorExit
异常仅在将yield值发送到客户端时才会引发。因此,如果Redis的listen()
永远不会结束,则永远无法发现连接已断开。