Reputation: 1125
I'd like to write my application state as a
reduce
(or rather scan
) function over all input observables.
const inputStream$ =
Rx.Observable.merge(all$, observables$, Im$, interested$, in$);
const outputStream$ = inputStream$.scan(accumulator, initialState);
As the inputStream$
can contain any value, the accumulator
function
would have to do a lot of type checking which seems rather fragile.
What I am looking for is something like:
function accumulator (acc, x) {
switch (x) {
case "all$ has fired":
return newState0;
case "observables$ has fired":
return newState1;
case "Im$ has fired":
return newState2;
case "interested$ has fired":
return newState3;
case "in$ has fired":
return newState4;
} }
Is this possible?
Upvotes: 2
Views: 319
Reputation: 506
You can always do something else - use multiple functions instead of "events" and one big function with switch
statement. Each event can be mapped to function that changes state the way you like. See example:
a = a.map(e =>
(currentState) => newState0
);
b = b.map(e =>
(currentState) => newState1
);
const inputStream$ = Rx.Observable.merge(a, b, ...);
const outputStream$ = inputStream$.scan((currentState, mod) =>
mod(currentState),
initialState);
The advantage of this approach is decoupling of logic of changing state. You can see how state is mutated in reaction for an event next to the event declaration. Each event creates its state modifier, but there is no problem if you want to use the same modifier for couple of them (for example click on the button or keyboard shortcut).
Upvotes: 1
Reputation: 39182
Sure. Just apply the map
operator to each input stream to add a discriminator to the value before merging it:
Rx.Observable.prototype.tag = function (tag) {
return this.map(value => ({ tag, value }));
};
const inputStream$ = Rx.Observable.merge(a.tag("a"), b.tag("b"), ...);
const outputStream$ = inputStream$.scan(v => {
const value = v.value;
switch (v.tag) {
case "a": return newState0;
case "b": return newState1;
...
}
}, initialState);
Upvotes: 1