How to implement a data loading activity indicator (spinner)?

Hi all, I’d like to show an activity indicator while the data is loading, then render a chart when data is loaded. What’s the best way of achieving this?

I was thinking about having a global isDataLoaded boolean cell that flips after async data loading is done. I’m doing data = d3.tsv(dataUrl, d3.autoType) and find it weird that it returns the data synchronously instead of returning a promise. I’m also not sure how to change the value of a declared isDataLoaded cell.

For the title question, these notebooks come to mind:

Regarding the questions in your post:

Assuming that you’re describing the behavior that occurs when data is its own cell, note that the Observable runtime implicitly awaits cells that return promises.

Not sure if this is the best way to accomplish what you want, but you could use a mutable cell for isDataLoaded. Then you would assign to it inside another cell using something like this:

// code to load data
// ...
// all done!
mutable isDataLoaded = true;

Note that cells that should be re-evaluated when isDataLoaded changes from false to true (or vice versa) should reference isDataLoaded (and not mutable isDataLoaded).

2 Likes

Thank you! Somehow I searched for all the keywords except “progress”. I think I have all the tools I need now. I’ll play with this.

Was this resolved ?

I want to have a load indicator for potentially large (hundreds MB) user submitted files, and have a fairly simple solution with a mutable indicator which shows that a file is currently loading. ‘Loading’ here means getting a reference to the file’s arrayBuffer(), after resolution of the returned Promise.

Is it somehow possible to get intermediate feedback on how far the arrayBuffer resolution progressed ? It seems to take about 5-10 seconds for a Gigabyte. I do not really think the File API provides for that but perhaps there is a way ? Load a file partially, in segments ?

Perhaps it is best just to add a fake count down ending in “still loading …” .

I will try to add a short example notebook.

[Please do not judge the idea of dealing with huge files in a browser :upside_down_face:]

ah, I should have looked at the fetch progress notebook. Reader.read may work with ObjectUrls.

Just confirming that fetch response.body.getReader().read does work with ObjectURLs created from blobs of large files.

Later edit since consecutive replies are somehow discouraged:

Hm, but it turns out that the streaming is actually quite a bit slower than the time it takes to make the blobs arrayBuffer available. Eg. Reader.read() is still delivering chunks after the arrayBuffer can already be processed. Oh well, this might be fine for a progress indicator. It is just a bit slow.

It actually looks like while the arrayBuffer is read, there may be locking similar to:

So the streaming may only start after the buffer is already read. I guess one has to choose, requesting the full arrayBuffer or streaming buffer chunks and finally merging.

On another note, getReader or streams are only supported in Firefox >= 65. Debian has by default Firefox 60.9esr . This makes this option less feasible.

1 Like