sinuous
sinuous copied to clipboard
Computed still updating (and subscribed to input observables) while output not observed
When trying the following code
const obs = observable(1);
const observer = () => { console.log("inside: " + obs()); return obs() };
const comp = computed(observer);
const unsub = subscribe(() => console.log(comp()));
obs(2);
unsub();
obs(3);
unsubscribe(observer);
obs(4);
we get the output
inside: 1
1
inside: 2
2
inside: 3
while I would kind of expect the logs from inside the computed to stop after the unsub()
. But this is only the case when I call unsubscribe
on the function that went into computed
(which also puzzled me a bit).
Is it desirable that computed
s still fire internally even when their output (data
) is not subscribed to?
I think my use case with the pipe
functionality that I am building would benefit greatly from automatic internal unsubscribe from a computed
s observable
inputs, because that would propagate up the chain, eventually allowing me to detect a whole chain has become unobserved at the beginning of the chain, which then allows me to stop the Websocket connection that produces the data for the chain.
thanks for the feedback, I removed the bug label for now but what you explain does makes sense to me. I'm not sure it's possible to change this behavior though without breaking things.
another call to comp()
in the end would have to have an updated value of course but it could be more like a lazy evaluation then.
wonder what S.js and MobX does in this case? do you happen to know?
I investigated a little further and it seems that the data()
function that is returned from a call to computed()
is different from the data()
returned by observable()
. The one from observable
has ._observers
but the one from computed
does not. So it seems the data
returned from computed
does not keep track of who is observing it and executing the observers when changes occur to it. And so it also doesn't know when it isn't being observed and doesn't know when to internally unobserve the observables inside.
I'm not sure about S or MobX's workings I'm afraid.
Mobx has ref counting for computeds, disposing them when not in use.
Sjs use roots for this purpose, disposing all computations at once, but not until dispose is called. This results in zombie computations that will keep working until parent disposed or re-run.