Refresh cells on a timer

So I have a notebook with many cells that I want to update continuously, at a given interval, say 1 update per second (sync doesn’t matter). I’ve been doing this with multiple Promise.delay/yield calls, but the code gets messy quickly.

Is there a way to do this more cleanly (in a single place) for a notebook with many cells ?

yeah I would have once cell name tick with the yield/delay. Then on every cell just reference the tick variable. e.g.

myothercell = {
   tick // cause recalc on tick, but otherwise ignore the variable value
   ... other stuff
}

Mmm, that is very nice, thank you.

But what if I wanted them to update one at a time? I’m thinking about graphical elements primarily, where I don’t want a big flash every second where everything changes at once…

Does this help How Observable Runs / Observable / Observable ?

Thanks for that, I now have a better understanding of the design thinking. And I may well be cutting against its grain, but I still think the use case is… useful. Ideally I could provide an array of cell-names (the slowly updating graphical elements), and have each updated every K milliseconds, but with a unique offset for each, so they don’t all trigger at once.

Q: is there a way to programmatically force an update of a cell from another cell (without cross-cell references ) ?

Q: can one access the graph of cells directly ?

Q: is there a way to programmatically force an update of a cell from another cell (without cross-cell references ) ?

Not in an idiomatic way

Q: can one access the graph of cells directly ?

Checkout Notebook visualizer / Observable | Observable

I don’t think there is an easy way to do it as a cell. Although many things are possible so maybe but you probably don’t want to.

Hmm, I see how it might be done by iteration over the runtime _variables property and finding the desired cells, but, as you say, it is working quite against the observable grain…

One other question: is there a way to disable propagation of updates to downstream references of a cell?

My guess is that your answer is the same: likely possible, but not in an intended/idiomatic way.

Good question. I have thought about whether it’s possible to slow down update frequency too. It is possible! here is a PoC Observable's 'now' temporal spacing is 60 or 30 frames per second. / Tom Larkworthy / Observable

You can return an unresolved promise to “skip” updates.

Another useful expression is “this” which refers to the previous value of a cell. So if you wanted to skip an update based on the previous state without introducing an adjacent cell to carry over state you might use ‘this’.

If the update is triggered by a parent cell, then no:

You can use mutable to “loosely” link cells.

If the update is triggered by a parent cell, then no:

Yes you can, return new Promise(() => {}) in the child to skip propagating an update when a parent updates.

“The previously-resolved value continues to be visible to other cells until the newly-yielded value resolves: in other words, a generator cell’s apparent value is the most-recently resolved value. For example, if you have a slowly-incrementing counter, you can reference it from another cell and see the current count instantly, rather than waiting for the next tick.” – Mike Bostock
in Introduction to generators / Observable | Observable

Imo that’s only marginally useful, since any downstream cell will still be invalidated. So it’s fine for one-off cells that only compute a value, but any generator, including viewof cells, will stop producing values.

Maybe I don’t understand something but doesn’t the experiment in Observable's 'now' temporal spacing is 60 or 30 frames per second. / Tom Larkworthy / Observable (make sure you scroll to the “slow_now” cell) demonstrate downsampling behaviour against an generator? I have measured the downstream revaluation frequency and its 10x less after using the unresolved promise trick.

I too was worried that if a cell is streaming out unresolved promises then dependants would just in an undefined state, but thats why I linked to what Mike Bosock said. It seems the runtime caches the last known value so they just work off the old value until a new one is actually resolved. Intermediate unresolved promises don’t cause an update to downstream cells. Its very cool that it works!

1 Like

I’ve added a section to Fighting Against (Run-)Time / Fabian Iwand / Observable - notice how the ticks_since_hours_invalidation generator cell never counts up higher than 2.

1 Like

yes you are right, thanks for sticking with me. I did not understand your notebook properly before.

Kinda of annoying the update frequencies can only go up. but I guess there are a few work arounds.

1 Like

No worries, I didn’t exactly make it easy to understand. Hopefully the new section is easier to digest.

1 Like