At Potions we are implementing an actor model based on RxJS.
We therefore need to be able to “hookup” an actor to the main channel.
An actor holds a behaviorSubject _state$, an in$ stream, an out$ stream and an
action function
(in$, state$) ⇒ (out$)
It is very similar to the redux-observable epic : https://redux-observable.js.org/docs/basics/Epics.html
Except that we consider that we can have multiple “stores”… Our “actors”.
As explained in this video https://www.youtube.com/watch?v=Vg60lf92EkM&list=PLNYkxOF6rcIDjlCx1PcphPpmf43aKOAdF&index=19
the actor model shift the mental model toward state rather then UI framework.
Hooking up a new actor means that the in$ stream becomes the channel$ stream
and the out$ stream pours its data in the channel$ stream.
The first part seams easy
javascriptin$ = channel$.asObservable()
However the second part is trickier.
We could think to just subscribe the channel$ to the out$ like that
javascript// This is wrong actorA.out$.subscribe(channel$) actorB.out$.subscribe(channel$)
But the problem with this code is that we don’t want the channel$ subject to complete as soon as an actor complete !
javascripta = new Subject() b = new Observable(observer => observer.complete()) c = new Observable(observer => observer.next(42)) a.subscribe(console.log) b.subscribe(a) c.subscribe(a) // Doesn't log 42 !!
javascripta = new Subject() b = new Observable(observer => observer.complete()) c = new Observable(observer => observer.next(42)) merge(b,c).subscribe(a) // Works but requires to know b and c prior to suubscribing
Here is our little trick to avoid completing the channel when a source completes :
javascripta = new Subject() b = new Observable(observer => observer.complete()) c = new Observable(observer => observer.next(42)) d = new Observable(observer => observer.next(50)) const neverComplete = mergeWith(NEVER) const mergeIn = a => b => { b.pipe(neverComplete).subscribe(a) } [b, c, d].map(mergeIn(a)) // Works !!