You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Bokeh中实现全局共享数据初始化及多UI元素复用的可行性问询

在Bokeh中实现全局共享数据初始化及多UI元素复用的可行性问询

当然可以实现!你的思路完全找对了方向——利用Bokeh的文档生命周期事件,结合浏览器的全局window对象存储共享数据,就能完美解决你提到的三个核心需求:只初始化一次数据、全局复用复杂结构、避免重复传参导致HTML体积膨胀。咱们来调整下你的代码,让它正常运行并贴合你的实际场景:

首先修正你代码里的小细节(比如缺失的Button导入、初始化执行的小问题),给出可运行的优化版本:

from bokeh.models import Div, CustomJS, Button  # 补上Button组件的导入
from bokeh.layouts import column
from bokeh.plotting import show
from bokeh.io import curdoc

# 初始化全局共享数据的代码,这里可以直接注入你的复杂数据结构
init_code = CustomJS(code="""
    // 挂载共享数据到全局window对象,所有UI元素的JS回调都能访问
    window.sharedData = { 
        initialized: true,
        // 示例:对应你上下文里的动态时间框架数据结构
        timeFrameData: {}
    };
    console.log("全局共享数据初始化完成", window.sharedData);
""")

# 第一个按钮:直接访问全局共享数据
button1 = Button(label="Log Complex Data", button_type="success")
button1.js_on_click(CustomJS(code="""
    console.log("当前共享数据:", window.sharedData);
    // 对应你上下文的步骤逻辑:遍历动态时间框架
    for (const [timeframe, data] of Object.entries(window.sharedData.timeFrameData)) {
        console.log(`处理时间框架: ${timeframe}`, data);
        // 可通过ID获取ColumnDataSource实例并操作
        const cds = Bokeh.documents[0].get_model_by_id(data.data_source_ref);
        // 执行你的过滤、更新逻辑...
    }
"""))

# 可以添加N个按钮,无需重复传递大参数
button2 = Button(label="Mark Data Updated", button_type="warning")
button2.js_on_click(CustomJS(code="""
    window.sharedData.lastUpdated = new Date().toISOString();
    console.log("共享数据已标记更新:", window.sharedData);
"""))

layout = column(button1, button2)  # 连dummy_div都可以省略了

# 核心:文档加载完成时执行初始化,确保只运行一次
curdoc().on_event('document_ready', lambda _: init_code.execute())

curdoc().add_root(layout)
show(layout)

关键实现细节说明:

  1. 仅初始化一次数据:通过document_ready事件触发初始化代码,这个事件只会在Bokeh文档完全加载后触发一次,完美匹配你"数据只初始化一次"的需求,比依赖Div的change事件更直接可靠。
  2. 全局复用复杂结构:把你的复杂数据(包括动态时间框架下的ColumnDataSource信息、DataFrame转译后的字典)都挂载到window.sharedData上,所有按钮的JS回调都能直接访问,不用给每个CustomJS重复传递大参数,从根源上避免HTML文件体积膨胀。
  3. 适配你的动态场景:针对你提到的"时间框架数量未知、动态生成按钮"的需求,JS里可以直接遍历window.sharedData.timeFrameData,通过ColumnDataSource的ID从Bokeh文档中获取实例,执行过滤、更新操作,完全适配动态逻辑。

针对你上下文场景的补充提示:

如果要把你真实的复杂数据注入到共享对象中,可以在Python端把数据转成JSON格式字符串,直接嵌入到初始化代码里:

# 示例:把你的js_data转成JSON字符串注入到初始化代码
import json
complex_data = json.dumps({
    "1h": {
        "candle_data": df_1h.to_dict(orient="list"),
        "data_source_ref": cds_1h.id
    },
    "4h": {
        "candle_data": df_4h.to_dict(orient="list"),
        "data_source_ref": cds_4h.id
    }
})

init_code = CustomJS(code=f"""
    window.sharedData = {{ 
        initialized: true,
        timeFrameData: {complex_data}
    }};
    console.log("全局共享数据初始化完成", window.sharedData);
""")

这样就完全实现了你想要的效果,既满足技术需求,也贴合你的实际业务场景~

备注:内容来源于stack exchange,提问作者elaspog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 12:58:03