bwl*_*lee 13 python flask server-sent-events
也许这是Flask的一个问题,没有办法在服务器端处理断开连接事件.
在Response类中,有一个名为"call_on_close"的方法,我们可以在其中添加一个没有参数的函数,例如on_close(),它会在响应对象的close方法被调用时触发,但是当我调用EventSource时这不会发生.在Javascript中从客户端关闭().
服务器端的代码:
from flask import Response
r = Response(stream(), ...)
r.call_on_close(on_close)
return r
def on_close():
print "response is closed!"
def stream():
... # subscribe to redis
for message in pubsub.listen():
....
yield 'data: %s\n\n' % message
Run Code Online (Sandbox Code Playgroud)
在客户端:使用SSE向页面添加卸载处理程序
$(window).unload(
function() {
sse.close();
}
}
Run Code Online (Sandbox Code Playgroud)
什么都错了?
任何建议或解决方案与代码表示赞赏!
提前致谢!
生成器收到一个GeneratorExit异常,然后你就知道它会退出。例如:
def stream():
try:
i = 0
while True:
yield 'Hello {}!'.format(i)
i += 1
time.sleep(1)
finally:
# Called after a GeneratorExit, cleanup here
i = 0
@app.route('/messages')
def messages():
return Response(stream(), content_type='text/event-stream')
Run Code Online (Sandbox Code Playgroud)
将产生无限流"Hello!",您将知道何时完成,您可以在哪里运行清理代码。如果您的生成器阻塞了线程,则需要以某种方式解除阻塞(可能是推送一个虚拟项目),以便可以关闭生成器。
小智 2
我在使用 Rails Live Controllers 时也遇到过类似的问题。问题在于框架似乎没有检测到连接已关闭,直到它尝试向客户端发送事件。
一种方法是向客户端发送周期性的“心跳”事件。我目前在我的 Rails 项目中成功使用了它,间隔为 60 秒。我有一个单独的线程,将这些心跳“发送”到 Redis 中,我的控制器已订阅该线程。
线程方法的另一种替代方法是使用超时(同样为 60 秒)来包装 Redis pubsub 块。然后将心跳事件发送到客户端 - 接下来是另一个 pubsub 调用。这种方法的缺点是,如果您没有订阅,您可能会错过某个活动。
这里有更多关于线程方法的信息: Redis + ActionController::Livethreads not dead