如何在 plotly/dash 应用程序中接受推送通知?

How to accept push notifications in a plotly/dash app?

我有一个与服务器建立连接的客户端,该服务器接受来自服务器的推送通知。我想在 plotly/dash 页面中近乎实时地显示来自推送通知的数据。

我一直在考虑 documentation page 中讨论的选项。

如果我在每个潜在的 plotly/dash 工作进程中有多个推送通知客户端 运行ning,那么我必须管理重复数据删除事件,这是可行的,但代码容易出错且古怪。

想法解决方案似乎是 运行 仅在一个进程上推送网络客户端,并将这些通知推送到 dcc.Store 对象中。我假设我会通过在推送客户端异步回调中填充一个队列来做到这一点,并在 dcc.Interval 计时器上收集该队列中的任何新数据并将其放入 dcc.Store 对象中。然后在 dcc.Store 对象上触发所有其他回调,可能在单独的 python 进程中。

从文档中我看不出如何保证与推送网络客户端交互的回调到主进程并确保它不会 运行 在任何工作进程上。这可能吗? dcc.Interval documentation 没有提到这个细节。

Is there a way to force the dcc.Interval onto one process, or is that the normal operation under Dash with multiple worker processes? Or is there another recommended approach to handling data from a push notification network client?

Interval 组件定期拉取更新的替代方法是使用 Websocket component 启用推送通知。只需将组件添加到布局并添加一个客户端回调,该回调根据收到的 message

执行适当的更新
app.clientside_callback("function(msg){return \"Response from websocket: \" + msg.data;}",
                        Output("msg", "children"), [Input("ws", "message")])

这是一个使用 SocketPool 设置端点以发送消息的完整示例,

import dash_html_components as html
from dash import Dash
from dash.dependencies import Input, Output
from dash_extensions.websockets import SocketPool, run_server
from dash_extensions import WebSocket

# Create example app.
app = Dash(prevent_initial_callbacks=True)
socket_pool = SocketPool(app)
app.layout = html.Div([html.Div(id="msg"), WebSocket(id="ws")])
# Update div using websocket.
app.clientside_callback("function(msg){return \"Response from websocket: \" + msg.data;}",
                        Output("msg", "children"), [Input("ws", "message")])


# End point to send message to current session.
@app.server.route("/send/<message>")
def send_message(message):
    socket_pool.send(message)
    return f"Message [{message}] sent."


# End point to broadcast message to ALL sessions.
@app.server.route("/broadcast/<message>")
def broadcast_message(message):
    socket_pool.broadcast(message)
    return f"Message [{message}] broadcast."


if __name__ == '__main__':
    run_server(app)