Closed tomlarkworthy closed 3 years ago
You should use the invalidation
promise for this. Promises.never, as designed, will never resolve, and thus tends to leak associated resources. If you use the invalidation
promise instead, those resources can at least be cleaned up if the cell is re-evaluated.
I'm fine with my code as-is but maybe I should explain what I'm doing and there's a better solution?
I do use invalidation
to clean up resources, but I'm using the unresolvable promise for something else. Effectively, the notebook has two states, uninitialized and running (recording sound). The straightforward way to handle this is to write code in each cell to handle both states wherever it matters. To avoid cluttering up the code with null checks, I decided to return an unresolvable promise for the audioContext
when the uninitialized state, which prevents downstream cells from running at all.
(The logic is slightly messy because the state machine has a transition from running back to uninitialized and downstream cells won't be rerun in that case, but it happens to be harmless.)
Perhaps that's too clever by half? The uninitialized state exists because browsers seem to disallow audio without user interaction, but the notebook isn't really about the state machine. It seems like notebooks are a bit of an awkward fit for writing apps with a global state machine, since each cell needs to handle all states.
@skybrian I think you could do this, and it would work:
if (!running) return invalidation; // Spin until this cell reruns for some reason.
Okay, I understand now. Yes it does work. Thank you!
This is a separate issue, but it occurs to me that the Observable runtime could be modified to provide a more elegant way of cleanly returning to the page's uninitialized state. Suppose a cell could return a special value that causes the runtime to reset all downstream cells to undefined
without evaluating their definitions? (Also, any downstream invalidation promises should be run.)
Wow using the invalidation promise is a great idea.
Add promises.never as alternative to returning an unresolved promise.
I often return new Promise(() => {}) to hold up the dataflow, but this is ugly. Its not just me, see https://talk.observablehq.com/t/audio-worklet-example/5138 So this is a more readable alternative that I think belongs with the Promises utilities.