sinuous icon indicating copy to clipboard operation
sinuous copied to clipboard

Computed still updating (and subscribed to input observables) while output not observed

Open quixot1c opened this issue 3 years ago • 3 comments

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 computeds 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 computeds 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.

quixot1c avatar Apr 07 '21 19:04 quixot1c

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?

luwes avatar Apr 10 '21 16:04 luwes

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.

quixot1c avatar Apr 10 '21 21:04 quixot1c

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.

Freak613 avatar May 11 '21 11:05 Freak613