Asynchronous Dash Callbacks

Is there a way incrementally return the values from chained callbacks? Below is a description of what I’m trying to accomplish and my attempt at a solution.

Desired behavior: Modal opens immediately on button click, an expensive computation is done, then modal closes.
Actual behavior: Modal opens until after everything has completed.

import dash_bootstrap_components as dbc
from dash import html, Input, Output, State
from dash_extensions.enrich import DashProxy, MultiplexerTransform
import time

app = DashProxy(
    __name__,
    transforms=[
        MultiplexerTransform(),  # makes it possible to target an output multiple times in callbacks
    ]
)

app.layout = html.Div([
    html.Div(id='dummy-div'),
    dbc.Button("Open modal", id="open", n_clicks=0),
    dbc.Modal([dbc.ModalBody("This should open on button click and should close after expensive computation."),],
        id="modal",
        is_open=False,
    ),

])

@app.callback(
    Output("modal", "is_open"),
    Input("dummy-div", "children")
)
def some_fun(children):
    if children:
        'Expensive computation...'
        time.sleep(5)
    return False
    

@app.callback(
    [
        Output("dummy-div", "children"),
        Output("modal", "is_open"),
    ],
    Input("open", "n_clicks"),
    State("modal", "is_open"),
)
def toggle_modal(n1, is_open):
    if n1:
        return [not is_open, not is_open]
    return [is_open, is_open]

if __name__ == '__main__':
    app.run_server(debug=True)```
2 Likes