Home > Net >  Rxjs pipe function with multiple filter() and switchMap() operators in the chain
Rxjs pipe function with multiple filter() and switchMap() operators in the chain

Time:12-15

I'm in the midst of refactoring some old rxjs code which was written poorly and therefore has some race conditions.

So I'd like to use a chain of filter() operators based on various conditions; however I need it to visit EVERY filter operator along this chain. i.e. If Condition1 is true, execute the next switchMap() - otherwise just follow down to the next filter(). Apply the same logic to Condition2..Condition4.

Also, my selectedNode needs to be emitted down the chain because the getChildNodes() function fetches additional child nodes and pushes them onto selectedNode.

Right now it just bails on when it encounters the first FALSY condition - so naturally the rest of the filters will never get checked.

How do I make it such that if will execute as an old IF...THEN statement on each condition?

Here's what I have so far:

    constructor(private readonly configSvc: ConfigService) {
        this.model$
            .pipe(
                filter((selectedNode) => !!selectedNode),

                // if condition1 passes, get child nodes of current node.
                filter((selectedNode) => myCondition1),
                switchMap((selNode) => this.getChildNodes(selNode, NodeType.Type1)),

                // if condition2 passes..
                filter((selectedNode) => myCondition2),
                switchMap((selNode) => this.getChildNodes(selNode, NodeType.Type2)),

                // if condition3 passes..
                filter((selectedNode) => myCondition3),
                switchMap((selNode) => this.getChildNodes(selNode, NodeType.Type3)),

                // if condition4 passes, get child nodes...
                filter((selectedNode) => myCondition4),
                switchMap((selNode) => this.getChildNodes(selNode, NodeType.Type4)),

                takeUntil(this.onDestroy),
            )
            .subscribe({
                next: (selectedNode: SelectedNode) => { // init the Network tree and notify listeners
                    this.initNetwork(selectedNode);
                    this.configNodesReadySource.next(selectedNode);
                },
            });
    }

or perhaps subscribing to mult observables, an an alt idea:

const condition1$ = this.model$.pipe(filter((node) => condition1), switchMap(...);
const condition2$ = this.model$.pipe(filter(...), switchMap(...);
const condition3$ = this.model$.pipe(filter(...), switchMap(...);
const condition4$ = this.model$.pipe(filter(...), switchMap(...);

forkJoin(...).subsribe(...); // join condition1 thru 4 to get final result ???

However, it seems I have the same problem or similar. I NEVER reach the subscribe.

CodePudding user response:

You can use concatMap to achieve cascading as described

this.model$
.pipe(
    filter((selectedNode) => !!selectedNode),
    concatMap(selectedNode => myCondition1 ? this.getChildNodes(selectedNode, NodeType.Type1) : of(selectedNode)),
    concatMap(selectedNode => myCondition2 ? this.getChildNodes(selectedNode, NodeType.Type2) : of(selectedNode)),
    concatMap(selectedNode => myCondition3 ? this.getChildNodes(selectedNode, NodeType.Type3) : of(selectedNode)),
    concatMap(selectedNode => myCondition4 ? this.getChildNodes(selectedNode, NodeType.Type4) : of(selectedNode)),
    takeUntil(this.onDestroy),
)
.subscribe({
    next: (selectedNode: SelectedNode) => { // init the Network tree and notify listeners
        this.initNetwork(selectedNode);
        this.configNodesReadySource.next(selectedNode);
    },
});
  • Related