【问题标题】:How to use combineLatest with filter in certain observable?如何在某些 observable 中使用 combineLatest 和过滤器?
【发布时间】:2023-04-07 00:05:02
【问题描述】:

这是对复杂情况的简化,如果值无效,可以过滤数组中的一些可观察值。问题是过滤后的 observable 不允许另一个完成组合。什么运营商或方法可以处理这种情况,允许订阅中的有效数据日志?

// RxJS v6+
import { fromEvent, combineLatest, of } from 'rxjs';
import { mapTo, startWith, scan, tap, map, filter } from 'rxjs/operators';

const userData$ = [
   of({ name: 'Joseph', age: 23}), 
   of({ name: 'Mario', age: 33}), 
   of({ name: 'Robert', age: 24}), 
   of({ name: 'Alonso', age: 25})
];

const names = ['Joseph', 'Mario', 'Robert', 'Alonso'];

combineLatest(
  names.map((name, i) => {
     return userData$[i].pipe(
         map(({name, age})=> { return{ name, age: age * 2} }),
         filter(({age}) => age < 67),
         map(({name, age})=> { return{ name: name.toLocaleUpperCase(), age} }),
     )
 })
)
   .pipe(
     tap(console.log),
   )
   .subscribe();

Sample in stackblitz

如果我们将值更改为 67,所有 observables 都会显示数据。

【问题讨论】:

    标签: javascript rxjs pipeline redux-observable combinelatest


    【解决方案1】:

    combineLatest 的一个典型问题是它要求所有源 Observable 至少发出一次,因此如果您使用 filter 丢弃它的唯一值,那么 combineLatest 将永远不会发出任何东西。

    一个简单的解决方案是确保它始终以defaultIfEmpty 发出:

    combineLatest(
      names.map((name, i) => {
        return userData$[i].pipe(
          map(({name, age})=> { return { name, age: age * 2} }),
          filter(({age}) => age < 66),
          map(({name, age})=> { return { name: name.toLocaleUpperCase(), age} }),
          defaultIfEmpty(null),
        )
      })
    )
    

    现场演示:https://stackblitz.com/edit/typescript-rsffbs?file=index.ts

    如果您的实际用例使用除 of() 之外的其他源 Observable 并不能立即完成,您可能希望改用 startWith

    【讨论】:

      【解决方案2】:

      您可以将combineLatest 替换为from,因为如果流数组中的任何一项没有发出,combineLatest 就不会发出

      const userData$ = [
        { name: 'Joseph', age: 23 },
        { name: 'Mario', age: 33 },
        { name: 'Robert', age: 24 },
        { name: 'Alonso', age: 25 }
      ];
      
      const names = ['Joseph', 'Mario', 'Robert', 'Alonso'];
      
      from(
        userData$
      )
        .pipe(
          map(({ name, age }) => { return { name, age: age * 2 } }),
          filter(({ age }) => age < 66),
          map(({ name, age }) => { return { name: name.toLocaleUpperCase(), age } }),
          tap(console.log),
        )
        .subscribe();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-03-03
        • 1970-01-01
        • 1970-01-01
        • 2020-08-31
        • 2020-10-19
        • 1970-01-01
        • 2021-03-06
        相关资源
        最近更新 更多