(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)