类似于 combineLatest 的 Rxjs 操作符,但如果只有一个发射则触发 [英] Rxjs operator similar to combineLatest but that trigger if only one emit

查看:75
本文介绍了类似于 combineLatest 的 Rxjs 操作符,但如果只有一个发射则触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

combineLatest的RxJs doc中,有写:

In the RxJs doc of combineLatest, there is writtent:

注意 combineLatest 不会发出初始值,直到每个observable 至少发出一个值.

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

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

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

推荐答案

假设 observables 是一个 observables 数组

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)
)

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

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.

同样的事情,但可能更健壮一点,因为它允许使用开发人员知道的形状的虚拟值.

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

你可以用任何东西替换'null'.例如:

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) 将忽略前 n 次发射:

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)
)

这篇关于类似于 combineLatest 的 Rxjs 操作符,但如果只有一个发射则触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆