Defer Long Running Tasks to Improve the User Experience
This guide addresses how to defer and orchestrate long running background tasks with pn.state.onload
. You can use this to improve the user experience of your app.
Motivation
When a user opens your app, the app is loaded as follows
the app file is executed
the app template is sent to the user and rendered
a web socket connection is opened to enable fast, bi-directional communication as your interact with the app.
Thus any long running code executed before the app is loaded will increase the the waiting time before your users see your apps template. If the waiting time is more than 2-5 seconds your users might get confused and even leave the application behind.
Here is an example of an app that takes +5 seconds to load.
Now lets learn how to defer long running tasks to after the application has loaded.
Defer a Task
Note that pn.state.onload
accepts both sync and async functions and also accepts a threaded
argument, which, when combined with enabling config.nthreads
will run the callbacks concurrently on separate threads.
This example could also be implemented using a bound and displayed function. We recommend using that method together with defer_load
when possible. See the Defer Bound and Displayed Functions Guide.
Defer and Orchestrate Dependent Tasks
Sometimes you have multiple tasks that depend on each other and you need to orchestrate them. To handle those scenarios you use pn.state.onload
to defer background tasks and pn.bind
to trigger bound and displayed functions when the the background tasks have finished.
Lets take an example where we
load a shared dataset.
display the dataset in a Table
transform the dataset and display it as a plot