typescript 在使用if语句进行嵌套订阅的情况下,正确的rxjs运算符是什么

pdtvr36n  于 2022-12-30  发布在  TypeScript
关注(0)|答案(3)|浏览(136)

我有2订阅角/ typescript 项目。
这2个订阅订阅它们自己的可观察的AB,它们在组件外部并且在服务文件中。
有时,基于某些组件动作,A改变,而B可能不改变,反之亦然,然而,通常B在另一组件中的A改变之后改变
此外,B必须在检查A的值是否正确之后才能执行操作,因此我所能想到的是使用if语句的嵌套订阅,如下所示。

ngOnInit(){
    this.A = this.serviceX.a.subscribe(
      data =>{ 
        this.temp = data;
        if(data=='correct'){
            this.B = this.serviceX.b.subscribe(
                beta => {
                    console.log('Sure'+this.temp);
                }
            )
        }
      }
    )
}

当它工作的时候?但是我看到其他的帖子说这不是一个好的方法。所以我尝试了combineLatestforkJoin。但是看起来他们只有在两个可观察的改变的时候才工作。并且如果其中一个可观察的根本没有改变,他们将不会被调用。如果我错了请纠正我。
所以现在所有我能想到的是单独订阅和订阅他们一个接一个像下面。

this.A = this.serviceX.a.subscribe(
  data =>{ 
    this.temp = data ;
  }
)
this.B = this.serviceX.b.subscribe(
  beta =>{ 
    if(this.temp=='correct'){
        console.log('Sure'+this.temp)
    }
  }
)

但是我非常担心我做错了,并且做了一个不稳定的迭代。我可以使用什么样的rxjs操作符来确保B订阅只在订阅A完成更改后订阅(然而A可能有时不会更改)?并最终使整个过程更健壮?

jhkqcmku

jhkqcmku1#

在subscribe处理程序中进行订阅可能会很麻烦,我相信这是可以避免的,而且应该永远避免。您的基本工作流程--就我对代码的理解而言--是这样的:
1.从serviceX.a检索数据
1.将数据存储为副作用
1.如果数据满足某些条件,则从serviceX.b检索数据
1.实际用户处理程序
现在你可以为每一步查找一个合适的操作符了,我是这样做的:

this.serviceX.a.pipe(                 // 1 - load from a
  tap(data => this.temp = data),      // 2 - side effect
  filter(data => data == 'correct'),  // 3a - if
  concatMap(() => this.serviceX.b)    // 3b - load from b
).subscribe((beta) => 
  console.log('Sure' + this.temp)     // 4 - actual subscribe
);

注意1:您只需要一个订阅。
注2:根据您的使用情况,您可能需要将concatMap替换为switchMapexhaustMapmergeMap
注三:在这里使用temp是相当危险的。根据您选择的*map运算符,您可能会创建一个竞态条件。在您等待serviceX.b发出时,serviceX.a可能已经发出下一个值并覆盖temp。如果temp的唯一原因是存储serviceX.a的结果,您应该使用以下解决方案:Is there an operator that lets me keep the initial value from a subscription after executing ,, switchMap"?

vltsax25

vltsax252#

也许你正在寻找flatMap,你可以Map多个订阅,每个flatMap应该返回它自己的Observable,并只订阅结束。

this.serviceX.a.pipe(flatMap(data => {
  this.temp = data;
  if (data == 'correct') {
    return this.serviceX.b.pipe(
      flatMap(beta => {
        this.temp2 = beta;
        console.log('Sure' + this.temp);
        return this.serviceX.c.pipe(map(delta => {
          this.temp3 = delta;
          console.log('Sure' + this.temp2);
          return delta;
        }));
      }));
  }
})).subscribe(delta => {
  console.log('Complete all subscriptions');
});
eqqqjvef

eqqqjvef3#

在另一个订阅中调用subscribe是一个不好的做法,因为您中断了流并从另一个流开始(在您的示例中,内部的订阅者从未被销毁,这可能会导致内存问题,每次流进入A时您都创建一个新的订阅者B,而此.B.Unsubscribe只销毁最后一个订阅者)。
然后,您需要继续使用mergeMapswitchMap运算符管理Stream,并在最后仅调用一个Subscribe。
为了过滤你的流,你可以使用filter操作符。

this.serviceX.a.pipe(                 
  filter((data: any) => data == 'correct'),  
  switchMap((value: any) => this.serviceX.b)     
)
.subscribe((value: any) => 
  console.log('Sure' + this.temp);     
);

之后,你只有1个订户,你需要取消订阅。

相关问题