简体   繁体   English

将 RxJS observables 与第一个操作符结合

[英]Combine RxJS observables with first operator

The question might no be the best cause I'm new to rxjs.这个问题可能不是最好的,因为我是 rxjs 的新手。 I apologize in advance.我提前道歉。

 this.route.queryParams.pipe(takeUntil(this.destroy$)).subscribe((queryParams) => {
      this.one();
      this.two();
    });

    this.route.queryParams.pipe(first(), takeUntil(this.destroy$)).subscribe((queryParams) => {
      this.three();
    });

Is it possible to combine these two observables into one?是否有可能将这两个 observable 合二为一? this.three needs to be fired only once, as first operator is used. this.three需要触发一次,因为使用了first运算符。

You can use combineLatest to combine observables that way if you need emitted value to do some control :如果您需要发出的值来进行一些控制,您可以使用combineLatest以这种方式组合可观察对象:

combineLatest([observable1$, observable2$]).subscribe(([val1, val2]) => {})

When any of your observables emits a value combineLatest will emit the last value of each, or you can use merge to get a single observable当您的任何 observable 发出一个值 combineLatest 将发出每个的最后一个值,或者您可以使用merge来获取单个 observable

You could use a merge to do it:您可以使用合并来做到这一点:

const queryParams$ = this.route.queryParams.pipe(share());

const executeOthers$ = queryParams$.pipe(
  tap(() => {
   this.one();
   this.two();
  })
);
const executeThree$ =  queryParams$.pipe(
  first(),
  tap(() => this.three())
);

merge(executeOthers$, executeThree$).pipe(
    takeUntil(this.destroy$)
).subscribe();

By doing so, you make sure that the three() method get executed on the first queryParams emission.通过这样做,您可以确保在第一个 queryParams 发射时执行了 Three() 方法。 The two other methods (one and two) will be executed on first and each time you change your route params.其他两种方法(一种和两种)将首先执行,并且每次更改路由参数时都会执行。

The cleanest solution is likely to just subscribe twice.最干净的解决方案可能只订阅两次。

If you do prefer to combine the two, I would do it like this:如果您确实更喜欢将两者结合起来,我会这样做:

this.route.queryParams.pipe(
  takeUntil(this.destroy$),
  map((value, index) => ({value, index})),
).subscribe(({value: queryParams, index}) => {
  if(index === 0){
    this.three();
  }
  this.one();
  this.two();
});

This adds an index right at the end of your stream, so you can know how many values have been emitted and use it to perform some logic.这会在流的末尾添加一个索引,因此您可以知道发出了多少个值并使用它来执行某些逻辑。


Another solution is to basically tap the first value.另一种解决方案是基本上tap第一个值。 Since tap doesn't give us an index, we can use map and pass values through unaltered.由于tap不给我们一个索引,我们可以使用map并通过原样传递值。

this.route.queryParams.pipe(
  takeUntil(this.destroy$),
  map((value, index) => {
    if(index === 0) this.three();
    return value;
  }),
).subscribe(queryParams => {
  this.one();
  this.two();
});

Another solution is to create a boolean that tracks if you're on the first value in a stream or not.另一个解决方案是创建一个布尔值来跟踪您是否在流中的第一个值上。 To do this, you're essentially required to create a custom operator.为此,您基本上需要创建一个自定义运算符。

this.route.queryParams.pipe(
  takeUntil(this.destroy$),
  o => defer(() => {
    let first = true;
    return o.pipe(
      tap(val => {
        if(first){
          this.three();
          first = false;
        }
      })
    )
  }),
).subscribe(queryParams => {
  this.one();
  this.two();
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM