let's say you have 2 observables:
const obs1$: Observable<string[]> = this.getObs1$();
const obs2$: Observable<string[]> = this.getObs2$();
i want to bine these 2 so that in subscription (or rxjs map) i know which emitted the values. I can't use bineLatest because for the other observable i just get the latest value it emitted at some point.
let's say you have 2 observables:
const obs1$: Observable<string[]> = this.getObs1$();
const obs2$: Observable<string[]> = this.getObs2$();
i want to bine these 2 so that in subscription (or rxjs map) i know which emitted the values. I can't use bineLatest because for the other observable i just get the latest value it emitted at some point.
Share Improve this question asked Jan 29, 2022 at 7:16 char mchar m 8,34618 gold badges73 silver badges129 bronze badges 3- Can't you add type for each observable? Something like this one: stackoverflow./questions/45455763/… – Alon Shmiel Commented Jan 29, 2022 at 8:01
-
2
You can chain each Observable with
map()
and wrap it with some data strucutre that you can use to identify the source. – martin Commented Jan 29, 2022 at 18:29 - this is what i did – char m Commented Feb 2, 2022 at 15:50
3 Answers
Reset to default 2There doesn't seem to be a purely RxJS solution to this (but hopefully someone can prove me wrong on that!)
You could use a variable in the outter scope to track the emitting observable as a workaround
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));;
bineLatest(....).subscribe(
// check trigger value
);
From the docs as a just-in-case: be aware that bineLatest will not emit an initial value until each observable emits at least one value
You can use merge
to bine the two observables into a single observable. Then, do what @martin suggested and map each source's emissions to a little structure that allows you identify the source:
const obs1$: Observable<number[]> = getNumbers();
const obs2$: Observable<string[]> = getLetters();
const bined$ = merge(
obs1$.pipe(map(data => ({ source: 'obs1$', data }))),
obs2$.pipe(map(data => ({ source: 'obs2$', data })))
);
bined$.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
...
Here's a little StackBlitz example.
I didn't get what I needed out of merge
but my go-to is bineLatestWith
this.transaction$
.pipe(takeUntil(this._ngUnsubscribe),
bineLatestWith(this.selectedStatus$)) // ngxs add latest sliced data to response
.subscribe(([status, tx]) => {
console.log(status, tx);
});
With NGXS its convenient to attach one of your slices via selector to also get the data in the response.