How to only fire callbacks after first callback is finished

Hi Dash Community:

Searched and saw some discussion, but want to get the latest optimal solution.

Scenario:
If I want my callback to refresh every 1 sec, controlled by the “n_intervals” with the respective “intervals” parameters.

At app start, the first execution of the callback will take long ( for instance, 30 sec ). However, in the subsequent executions it will take shorter due to caches done in the first callback.

If I follow the implementation above, you can expect that the calculation will get stuck as: before the first call finishes, the n_clicks keeps incrementing and firing subsequent callbacks before the first one is finishes.

I think this is a known issue. Was this the best solution so far? ( Example 2: Disable Button While Callback Is Running)

Thank you. Any suggestions are welcomed.

Hi @entropy_l,

you could return your dcc.Interval() once the background callback has finished:

import time
import datetime
import diskcache

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

# Diskcache for non-production apps when developing locally
cache = diskcache.Cache("./cache")
background_callback_manager = DiskcacheManager(cache)

app = Dash(
    __name__, 
    background_callback_manager=background_callback_manager, 
    suppress_callback_exceptions=True
)

app.layout = html.Div(
    [
        html.Div(
            id="paragraph_id", 
            children="background callback starts at app initiation"
        ),
        html.Div(id='interval_container'),
        html.Div(id='out')
    ]
)


@callback(
    output=[
        Output("paragraph_id", "children"),
        Output("interval_container", "children"),
    ],
    inputs=Input("interval_container", "style"),
    background=True,
)
def update_clicks(_):
    time.sleep(6.0)
    return [f"Background callback finished"], dcc.Interval(id='interval', interval=1 * 1000, n_intervals=0)


@app.callback(
    Output('out', 'children'),
    Input('interval', 'n_intervals')
)
def timestamp(_):
    return str(datetime.datetime.now())


if __name__ == "__main__":
    app.run(debug=True)
1 Like

Thank you AIMPED.

Sorry for the late reply. I was trying your method through the day. It works as expected, thank you.
I have two more notes here:

  • In this block:
    @app.callback(
    Output(‘out’, ‘children’),
    Input(‘interval’, ‘n_intervals’)
    )
    def timestamp(_):
    return str(datetime.datetime.now())

Should we prevent the call if the n_intervals is None? That is, before the children of interval_container is initiated.

  • I understand that “background_callback” may have its benefit, However, in this case, I should be able to achieve the same with regular callback? Meaning, using the regular callback to initiate the children of interval container. Then, in the “timesmap” callback, don’t update ( using exception Prevent_Callback" ) until the first callback is finished.

Appreciate your code and time, Thank you!

@entropy_l sure, you can use a regular callback for this. I used a background callback because you mentioned it and assumed your initial caching callback might run into server timeouts.