1

这是一个复杂情况的简化,如果值无效,可以过滤数组中的一些可观察值。问题是过滤后的 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();

stackblitz 中的示例

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

4

2 回答 2

3

一个典型的问题combineLatest是它要求所有源 Observables 至少发出一次,所以如果你使用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

如果您的实际用例使用其他源 Observable 而of()不是立即完成,您可能希望使用它startWith

于 2020-04-23T08:53:49.213 回答
0

如果流数组中的任何一项未发出,则可以替换combineLatestfromas combineLatestwon't emit

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();
于 2020-04-23T06:09:03.420 回答