(flask + socket.IO) 发出回调的结果是我的 REST 端点的响应
(flask + socket.IO) Result of emit callback is the response of my REST endpoint
只是在这里给出一个上下文,我是一名 node.JS 开发人员,但我正在从事一个项目,我需要使用 Flask 框架与 Python 合作。
问题是,当客户端请求我的 rest flask 应用程序的端点时,我需要使用 socket.IO 发出一个事件,并从套接字服务器获取一些数据,然后这个数据就是响应端点。但是我没有想出如何发送这个,因为 flask 需要一个 "return" 语句来说明响应是什么,而我的回调是在另一个上下文中。
我正在尝试做的示例:(有一些评论解释)
import socketio
import eventlet
from flask import Flask, request
sio = socketio.Server()
app = Flask(__name__)
@app.route('/test/<param>')
def get(param):
def ack(data):
print (data) #Should be the response
sio.emit('event', param, callback=ack) # Socket server call my ack function
#Without a return statement, the endpoint return 500
if __name__ == '__main__':
app = socketio.Middleware(sio, app)
eventlet.wsgi.server(eventlet.listen(('', 8000)), app)
也许,这里正确的问题是:这可能吗?
我将为您提供一种具体实现您想要的方法,但我相信您在这方面有一个重要的设计缺陷,正如我在上面的评论中所解释的那样。按照您的编码方式,您的 socketio.Server()
对象将广播给您的所有客户端,因此将无法获得回调。如果你想发送给一个客户端(希望不是发送 HTTP 请求的同一个客户端),那么你需要向发送添加一个 room=client_sid
参数。或者,如果您正在联系 Socket.IO 服务器,那么您需要在此处使用 Socket.IO 客户端,而不是服务器。
无论如何,要在调用回调函数之前阻止您的 HTTP 路由,您可以使用 Event
对象。像这样:
from threading import Event
from flask import jsonify
@app.route('/test/<param>')
def get(param):
ev = threading.Event()
result = None
def ack(data):
nonlocal result
nonlocal ev
result = {'data': data}
ev.set() # unblock HTTP route
sio.emit('event', param, room=some_client_sid, callback=ack)
ev.wait() # blocks until ev.set() is called
return jsonify(result)
只是在这里给出一个上下文,我是一名 node.JS 开发人员,但我正在从事一个项目,我需要使用 Flask 框架与 Python 合作。
问题是,当客户端请求我的 rest flask 应用程序的端点时,我需要使用 socket.IO 发出一个事件,并从套接字服务器获取一些数据,然后这个数据就是响应端点。但是我没有想出如何发送这个,因为 flask 需要一个 "return" 语句来说明响应是什么,而我的回调是在另一个上下文中。
我正在尝试做的示例:(有一些评论解释)
import socketio
import eventlet
from flask import Flask, request
sio = socketio.Server()
app = Flask(__name__)
@app.route('/test/<param>')
def get(param):
def ack(data):
print (data) #Should be the response
sio.emit('event', param, callback=ack) # Socket server call my ack function
#Without a return statement, the endpoint return 500
if __name__ == '__main__':
app = socketio.Middleware(sio, app)
eventlet.wsgi.server(eventlet.listen(('', 8000)), app)
也许,这里正确的问题是:这可能吗?
我将为您提供一种具体实现您想要的方法,但我相信您在这方面有一个重要的设计缺陷,正如我在上面的评论中所解释的那样。按照您的编码方式,您的 socketio.Server()
对象将广播给您的所有客户端,因此将无法获得回调。如果你想发送给一个客户端(希望不是发送 HTTP 请求的同一个客户端),那么你需要向发送添加一个 room=client_sid
参数。或者,如果您正在联系 Socket.IO 服务器,那么您需要在此处使用 Socket.IO 客户端,而不是服务器。
无论如何,要在调用回调函数之前阻止您的 HTTP 路由,您可以使用 Event
对象。像这样:
from threading import Event
from flask import jsonify
@app.route('/test/<param>')
def get(param):
ev = threading.Event()
result = None
def ack(data):
nonlocal result
nonlocal ev
result = {'data': data}
ev.set() # unblock HTTP route
sio.emit('event', param, room=some_client_sid, callback=ack)
ev.wait() # blocks until ev.set() is called
return jsonify(result)