zauberzeug / nicegui

Create web-based user interfaces with Python. The nice way.
https://nicegui.io
MIT License
9.74k stars 579 forks source link

ReferenceError: Plotly is not defined when creating many graphs #3784

Closed valankar closed 3 weeks ago

valankar commented 3 weeks ago

Description

Here is an example code similar to what I'm doing:

#!/usr/bin/env python3

import asyncio

from nicegui import ui

@ui.page("/")
async def main_page():
    """Generate main UI."""
    fig = {
        "data": [
            {
                "type": "scatter",
                "name": "Trace 1",
                "x": [1, 2, 3, 4],
                "y": [1, 2, 3, 2.5],
            },
            {
                "type": "scatter",
                "name": "Trace 2",
                "x": [1, 2, 3, 4],
                "y": [1.4, 1.8, 3.8, 3.2],
                "line": {"dash": "dot", "width": 3},
            },
        ],
        "layout": {
            "margin": {"l": 15, "r": 0, "t": 0, "b": 15},
            "plot_bgcolor": "#E5ECF6",
            "xaxis": {"gridcolor": "white"},
            "yaxis": {"gridcolor": "white"},
        },
    }

    async def make_plot():
        await asyncio.sleep(5)
        for _ in range(11):
            ui.plotly(fig).classes("w-full")

    await ui.context.client.connected()
    await make_plot()

ui.run()

When I run this, I get ReferenceError on the console:

vue.global.prod.js:5  ReferenceError: Plotly is not defined
    at Proxy.update ((index):94:9)
    at Proxy.updated ((index):81:10)
    at vue.global.prod.js:5:22240
    at tP (vue.global.prod.js:5:16075)
    at tF (vue.global.prod.js:5:16143)
    at vue.global.prod.js:5:22125
    at tY (vue.global.prod.js:5:17631)
    at e (vue.global.prod.js:5:17180)

image

If I take out the await ui.context.client.connected(), I end up with timeout errors:

...
  File "/home/valankar-dev/code/accounts/.venv/lib/python3.12/site-packages/nicegui/page.py", line 121, in decorated
    raise TimeoutError(f'Response not ready after {self.response_timeout} seconds')
TimeoutError: Response not ready after 3.0 seconds

Generally, this code is simulating my real code in generating Plotly graphs that take some time. How can I do this properly without getting either of these errors?

python-and-fiction commented 3 weeks ago
#!/usr/bin/env python3

import asyncio

from nicegui import ui

@ui.page("/")
async def main_page():
    """Generate main UI."""
    fig = {
        "data": [
            {
                "type": "scatter",
                "name": "Trace 1",
                "x": [1, 2, 3, 4],
                "y": [1, 2, 3, 2.5],
            },
            {
                "type": "scatter",
                "name": "Trace 2",
                "x": [1, 2, 3, 4],
                "y": [1.4, 1.8, 3.8, 3.2],
                "line": {"dash": "dot", "width": 3},
            },
        ],
        "layout": {
            "margin": {"l": 15, "r": 0, "t": 0, "b": 15},
            "plot_bgcolor": "#E5ECF6",
            "xaxis": {"gridcolor": "white"},
            "yaxis": {"gridcolor": "white"},
        },
    }

    async def make_plot():
        await asyncio.sleep(5)
        for _ in range(11):
            await asyncio.sleep(0.5)
            ui.plotly(fig).classes("w-full")

    await ui.context.client.connected()
    await make_plot()

ui.run()
valankar commented 3 weeks ago

What's the reason for adding the 0.5 sleep?

falkoschindler commented 3 weeks ago

Interesting bug, @valankar! Here is a minimum reproduction:

@ui.page("/")
async def main_page():
    await ui.context.client.connected()
    ui.plotly({})
    ui.plotly({})

One plot is ok, a second one causes a ReferenceError. Very strange!

falkoschindler commented 3 weeks ago

Adding this block to the update() method in plotly.vue seems to help:

// wait for plotly to be loaded
if (typeof Plotly === "undefined") {
  setTimeout(this.update, 10);
  return;
}