What is a “re-triggerable” callback?
Prior to Background Callbacks, I previously (and successfully) implemented a “re-triggerable” callback using the modified_timestamp
property of a dcc.Store component as a way to “re-trigger” the same callback. This “re-triggerable” callback contained logic for start/continue/end of the retriggered callback ‘chain’. This was a workaround for the gateway timeout for long running processes, and allowed display of progress update.
Now I am now trying to implement a similar mechanism with Clientside Callbacks to improve overall speed/performance of these callbacks. However, although I can trigger this clientside callback manually, it does not appear to retrigger using the same approach as above.
QUESTION:
Why do “re-triggerable” callbacks work for regular callbacks but does not seem to “re-trigger” when using clientside callbacks?
Thanks!
Example template code is shown below.
main.py
app.clientside_callback(
ClientsideFunction(
namespace="load_data",
function_name="getData"
),
Output('clientside-load-data-status-store', 'data'),
Output('clientside-load-data-status-progress-bar', 'value'),
Output('clientside-load-data-status-progress-bar', 'max'),
Input("load-data-bt", "n_clicks"),
Input('clientside-load-data-status-store', 'modified_timestamp'),
State('clientside-load-data-status-store', 'data'),
prevent_initial_call=True
)
assets.js
window.dash_clientside = Object.assign({}, window.dash_clientside, {
load_data: {
getData: async function loadData (n_clicks, status_modified_timestamp, status_data) {
let ctx = dash_clientside.callback_context
let triggered_prop_id = ctx.triggered[0]['prop_id']
let n_clicks_id = Object.keys(ctx.inputs)[0]
if (status_data['curr_page'] == 0 && status_data['total_pages'] == 0 && triggered_prop_id == n_clicks_id) {
// Start callback chain ...
status_data['curr_page'] = 1
// Get total pages from initial API call or other means ...
let total_pages = 3
status_data['total_pages'] = total_pages
}
else if (status_data['curr_page'] <= status_data['total_pages']) {
// Make API request for current page ...
status_data['curr_page'] += 1
}
else {
// End callback chain and reset ...
status_data['curr_page'] = 0
status_data['total_pages'] = 0
}
return [status_data, status_data['curr_page'].toString(), status_data['total_pages'].toString()]
}
}
});