Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rxjs conditional nesting observables

I have the following code which is working as intended:

const sourceObservable = ... // irrelevant
sourceObservable.subscribe(x => {
    doAnyway(x);
    if (x.Id) {             
        doSometing(x);
    } else {
        // id Not set, get default Id
        this.idService.getDefault().subscribe(id => {
            x.Id = id;                  
            doSometing(x);
        });
    }
});

According to this article nested subscribes are to avoid. Thats why i tried to refactor the above code, using pipes. I tried to realize the if-else operation with this Method, where filtering is used to create an observable branch for each option. And in the end they should be merged to subscribe.

const obsShared = sourceObservable.pipe(
tap(x => {
    doAnyway(x);
}),
share());

const obsIdNotSet = obsShared.pipe(
    filter(x => !x.kennzahlId),
    merge(x => idService.getDefault().subscribe(id => {
            x.Id = id;
        // doSomething(x) will nomore be executed here
        })));

// even though the true-part is empty I seem to need this to mergeing both options
const obsIdSet = obsShared.pipe( 
    filter(x => !!x.Id),
    tap(() => {
        // doSomething(x) will nomore be executed here
    }));

obsIdSet.pipe(merge(obsIdNotSet)).subscribe(x => {  
    // in case obsIdNotSet this will run with x.Id not set because x.Id will be set later
    doSometing(x);
});

This code does compile and run without errors, only does it execute doSomething(x) before calling idService.getDefault()..... and though it will be called without x.Id being set.

What am i doing wrong?

like image 949
LuckyLikey Avatar asked Sep 07 '25 03:09

LuckyLikey


1 Answers

the following is the cleanest way to handle that (according to me) :

source.pipe(
  tap(val => doAnyway(val)),
  switchMap(val => val.id ? of(val.id) : this.idService.getDefault())
).subscribe(id => {
  this.id = id;
  doSomething(id);
});

You can see how short and clear this is, and it does the exact same thing your first code was doing.