plotly / dash

Data Apps & Dashboards for Python. No JavaScript Required.
https://plotly.com/dash
MIT License
21.38k stars 2.06k forks source link

dcc.Loading Icon Not Displaying when another Function is Called #2268

Open matt-buckley opened 2 years ago

matt-buckley commented 2 years ago

Thank you so much for helping improve the quality of Dash!

We do our best to catch bugs during the release process, but we rely on your help to find the ones that slip through.

Describe your context Please provide us your environment, so we can easily reproduce the issue.

Describe the bug

When running a function with a dcc.Loading callback, if this function then calls another function which has a particularly long runtime (for example if it is loading in a large dataset) the loading icon will not always display until this called function returns and runtime continues in the original callback function. This occurs even when the callback is a background callback.

Expected behavior

The loading icon should display as soon as the callback function begins running.

nickmelnikov82 commented 2 years ago

Hello @matt-buckley.

Can you please provide an example app where this bug is reproduced?

matt-buckley commented 2 years ago

Unfortunately I can't provide the exact code I'm working on, but the pseudocode examples would be:

@app.callback( Output('figure', 'value'), Output('loading-icon-1', 'children'), # Series of Inputs ) def function(args): df = import_df(args) # Processing # Create fig return fig, ''

It's this import_df() call that seems to be causing the issues. Some further discussion is available at https://community.plotly.com/t/dcc-loading-not-working-with-long-function-calls/68772

AnnMarieW commented 8 months ago

@matt-buckley I can't replicate your issue. Can you make an example?


import time

from dash import Dash, Input, Output, html, dcc

def get_data():
    time.sleep(4)
    return

def make_figure():
    time.sleep(4)
    return

app=Dash()

app.layout = html.Div(
    [
        html.Button("Load", id="loading-button", n_clicks=0),
        html.Hr(),
        dcc.Loading(html.Div(id="loading-output"), id="loading"),
    ]
)

@app.callback(
    Output("loading-output", "children"),
    Input("loading-button", "n_clicks"),
)
def load_output(n):
    if n:
        get_data()
        make_figure()
        return f"Output loaded {n} times"
    return "Output not reloaded yet"

app.run(debug=True)