How do you get initial data asynchronously from a remote data source?

So my understanding is that you shouldn’t be making any blocking calls, because it’ll hold up the event loop.

But how do you get initial data from a remote source into the document then?

Whether it’s an early next tick call back or utilising the handler’s server lifecycle hooks… surely the thread of execution will then move on and attempt to utilise data that isn’t there yet?

I know you could have a button that gets the data and asynchronously updates the UI from that… but the constraints of this project dictate that upon page load (i.e. when an application’s document is rendered) that the data is already there for other buttons and controls to take advantage of.

Does that make sense?

Feels like I’m missing something obvious here…

Are the initial data static or do you need them to be updated each time the app renders?

Hi,

The answer depends. Blocking is mostly a problem in cases where you will have many concurrent users. If you only have one user at a time, I don't think it matters. Work that has to be done always still has to be done. If you only expect a few concurrent users then blocking still might be OK to block if you run multiple instances of the server behind a load balancer, or if --num-threads is an option. Otherwise, you can always explicitly offload work to a threads:
  
  https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads

  https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-unlocked-callbacks

Unfortunately there's not currently an especially good way to indicate back to the front end that long-running work is underway (i.e. to show a spinner or similar). There's an open issue for that, but there are lots of other priorities ahead of it. But you could always update a Div, etc to indicate mention that things are "processing".

Thanks Bryan, that’s really helpful :slight_smile:

Thanks Bryan!

FYI, This works until the page blocking spinner is implemented:

spinner_text = """
<!-- [https://www.w3schools.com/howto/howto_css_loader.asp](https://www.w3schools.com/howto/howto_css_loader.asp) -->
<div class="loader">
<style scoped>
.loader {
    border: 16px solid #f3f3f3; /* Light grey */
    border-top: 16px solid #3498db; /* Blue */
    border-radius: 50%;
    width: 120px;
    height: 120px;
    animation: spin 2s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}
</style>
</div>
"""
div_spinner = Div(text="",width=120,height=120)
def show_spinner():
    div_spinner.text = spinner_text
def hide_spinner():
    div_spinner.text = ""
show_spinner_button = Button(label='Show Spinner', width=100)
show_spinner_button.on_click(show_spinner)
hide_spinner_button = Button(label='Hide Spinner', width=100)
hide_spinner_button.on_click(hide_spinner)
1 Like

Brilliant, that never would have occurred to me. Thanks's for demonstrating perfectly how a more people contributing is better!

Would you mind mentioning this on the issue, so that folks who stumble across it can find the workaround as well:

  https://github.com/bokeh/bokeh/issues/3393

Done. :slight_smile:

Glad to help! Keep up the good work on Bokeh and the other tools at Continuum by you and the teams. Continuum’s tools are really helpful!

That’s really cool. Didn’t think of updating a Div text like that, this also works to show/hide a gif in folder apps

even simpler! thanks! :slight_smile: