ds300/derivablejs

Dependent Reactors

ds300 opened this issue · 1 comments

this text assumes I'm gonna rename Reaction to Reactor. See #15

Sometimes a Reactor's mode (active/dormant, running/stopped, whatever) is dependent on some piece of state S. Reactors can't start themselves, so it is natural to have a separate Reactor P which listens to S and starts/stops the dependent Reactor D accordingly.

This is fine, except when the piece of state T which D is listening to also depends on S. DerivableJS makes no guarantees about which order Reactors are traversed during a reaction phase. This means that D could dereference a derivable which should not be calculated given S. So P's reaction must be invoked before D's.

There are a couple other issues around this that I need to think about.

... And those issues involve whether or not dependent Reactors should be stopped when their parent Reactor is stopped and, if so, should it be possible to 'orphan' a dependent Reactor such that it becomes independent?

The only API change needed for any of this would be the orphaning operation. The dependencies can be inferred just like for Derivations.

Also, to illustrate the problem discussed in the top comment:

const arr = atom([0, 1, 2]);

// set up reactor to print 3rd elem of arr, but don't start it
const A = arr.reactor(arr => console.log(arr[2].toString()));

// instead control it by reacting to the length of the array
const B = arr.derive(a => a.length).react(len => {
  if (len >= 3) {
    if (!A.isRunning()) A.start().force();
  } else {
    A.stop();
  }
});
// $> 2

arr.set([0,1]);
// A and B get invoked
// but if A is invoked before B, the .toString() will
// throw an error because arr[2] is undefined

// but if B is invoked before A, A gets stopped before
// it has the chance to make that mistake