首页 > 解决方案 > Rxjs 操作符类似于 combineLatest 但如果只有一个发出就会触发

问题描述

在 的 RxJs 文档中combineLatest,写着:

请注意,在每个 observable 发出至少一个值之前, combineLatest 不会发出初始值。

是否有一个操作符可以工作,combineLatest但即使只有一个可观察对象发出一个值,它也会发出一个值?

标签: typescriptrxjs

解决方案


假设observables是一个可观察的数组

combineLatest(...observables.map(
  s => s.pipe(
    startWith(null)
  )
)).pipe(
  filter(arr => arr.filter(x => x != null).length > 0)
)

这将在源 observable 尚未发出的任何位置发出一个带有 null 的数组。它还过滤掉整个数组为空的第一个发射。


根据评论更新:

同样的事情,但可能更健壮一些,因为它允许具有开发人员知道的形状的虚拟值。

您可以用任何内容替换“null”。例如:

combineLatest(...observables.map(
  s => s.pipe(
    startWith({dummy: true})
  )
)).pipe(
  filter(arr => arr.filter(x => !x?.dummy).length > 0)
)

更新以提高性能:

在规模上,循环遍历数组以查看是否所有值都是 void/dummy 值对性能不利。因为(在这种情况下)我们只想忽略第一次发射,所以这个自定义操作符可以在不检查值的情况下做到这一点。

filterFirst(n)将忽略第一次n排放:

function filterFirst<T>(n: number): MonoTypeOperatorFunction<T>{
  return s => defer(() => {
    let count = 0;
    return s.pipe(
      filter(_ => n <= count++)
    )
  });
}

然后你可以按如下方式使用它:

combineLatest(...observables.map(
  s => s.pipe(
    startWith(null)
  )
)).pipe(
  filterFirst(1)
)

推荐阅读