rxjs条件嵌套可观察

Luc*_*key 2 rxjs typescript angular

我有以下代码可以正常工作:

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);
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

根据本文,嵌套订阅是要避免的。这就是为什么我尝试使用管道重构上述代码的原因。我尝试使用此方法实现if-else操作,其中使用过滤为每个选项创建一个可观察的分支。最后,它们应该合并以进行订阅。

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);
});
Run Code Online (Sandbox Code Playgroud)

该代码可以编译并运行,不会出错,仅doSomething(x)在调用之前执行idService.getDefault().....,尽管在未设置x.Id的情况下将被调用。

我究竟做错了什么?

小智 5

以下是处理此问题的最干净方法(根据我的说法):

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

您可以看到这是多么简短,而且很清楚,它与您的第一个代码所做的完全相同。