如何组合 2 个或更多 observables 以便你知道哪个发出了?

How to combine 2 or more observables so that you know which emitted?

假设您有 2 个可观察对象:

const obs1$: Observable<string[]> = this.getObs1$();
const obs2$: Observable<string[]> = this.getObs2$();

我想结合这两个,以便在订阅(或 rxjs 映射)中我知道哪个发出了值。我不能使用 combineLatest,因为对于其他可观察对象,我只是得到它在某个时候发出的最新值。

似乎没有一个纯粹的 RxJS 解决方案(但希望有人能证明我是错的!)

作为解决方法,您可以在外部作用域中使用变量来跟踪发射的可观察对象

let trigger: TriggerEnum;

const obs1$: Observable<string[]> = this.getObs1$()
  .pipe(tap(() => trigger = TriggerEnum.One));
const obs2$: Observable<string[]> = this.getObs2$()
  .pipe(tap(() => trigger = TriggerEnum.Two));;

combineLatest(....).subscribe(
 // check trigger value
);

来自文档 just-in-case:请注意,在每个可观察对象至少发出一个值之前,combineLatest 不会发出初始值

您可以使用 merge 将两个 observable 合并为一个 observable。然后,按照@martin 的建议进行操作,并将每个源的排放映射到一个允许您识别源的小结构:

const obs1$: Observable<number[]> = getNumbers();
const obs2$: Observable<string[]> = getLetters();

const combined$ = merge(
  obs1$.pipe(map(data => ({ source: 'obs1$', data }))), 
  obs2$.pipe(map(data => ({ source: 'obs2$', data })))
);

combined$.subscribe(
   ({ source, data }) => console.log(`[${source}] data: ${data}`)
);

// OUTPUT:
//
// [obs1$] data: 1
// [obs2$] data: A
// [obs2$] data: A,B
// [obs2$] data: A,B,C
// [obs1$] data: 1,2
// [obs2$] data: A,B,C,D
...

这里有一个 StackBlitz 的小例子。