下面给出了一个使用node.js的答案。
How to close a "Server-Sent Events"-connection on the server?
但是,如何在python Flask中做同样的事情?
嗯,这取决于你的应用程序的架构。
让我举个例子(参见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看到流终止时(StopIteration
,如果你不是Python的新手),它会返回。
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")
我有同样的问题,终于找到了以下解决方案here。
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的侦听器来启动该方法。而不是time.sleep(1)
你可以等待Redis的listen()
方法返回一个vlaue。您可以取消订阅Redis,而不是print('closed')
。剩下的唯一问题是只有在将yield值发送给客户端时才会引发GeneratorExit
异常。因此,如果Redis的listen()
永远不会结束,那么你永远不会发现连接已被破坏。