Rxjs operator similar to combineLatest but that trigger if only one emit

旧城冷巷雨未停 提交于 2021-01-07 06:36:55

问题


In the RxJs doc of combineLatest, there is writtent:

Be aware that combineLatest will not emit an initial value until each observable emits at least one value.

Is there an operator that works like combineLatest but that emit a value even if only one of the observable emits a value ?


回答1:


Assuming observables is an array of observables

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

This will emit an array with null in any position where the source observable hasn't emitted yet. It also filters out the very first emission where the entire array is null.


Update based on comment:

The same thing, but perhaps a bit more robust as it allows for a dummy value with a shape that the developer knows.

You can replace 'null' with anything. For example:

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

Update to improve performance:

At scale, looping through an array to see if all values are void/dummy values is bad for performance. Since (in this case) we only want to ignore the first emission, this custom operator can do that without checking the values at all.

filterFirst(n) will ignore the first n emmissions:

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

Then you can use it as follows:

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


来源:https://stackoverflow.com/questions/65039188/rxjs-operator-similar-to-combinelatest-but-that-trigger-if-only-one-emit

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!