rxjs条件嵌套可观察

时间:2018-11-19 10:10:32

标签: angular typescript rxjs

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

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);
        });
    }
});

应避免使用this article嵌套订阅。这就是为什么我尝试使用管道重构上述代码的原因。我试图用this Method实现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);
});

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

我在做什么错了?

1 个答案:

答案 0 :(得分:4)

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

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

您可以看到它有多短和清晰,并且它执行的代码与您的第一个代码完全相同。