I have two streams of objects, the accounts and balances.
I need to merge (join) the two streams according to the id
and account_id
If you have truly 2 observables that emit the results as Observable<{}>
in random order, this is a way you can combine them. If the order is not random, or if they always come in 'pairs', more efficient way's exists to combine them.
import { from, merge } from 'rxjs';
import { map, scan, tap } from 'rxjs/operators';
const accounts = from([
{ id: 1, name: 'account 1' },
{ id: 2, name: 'account 2' },
{ id: 3, name: 'account 3' }
]);
const balances = from([
{ account_id: 1, balance: 100 },
{ account_id: 2, balance: 200 },
{ account_id: 3, balance: 300 }
]);
interface Outcome {
id: number;
name?: string;
balance?: number;
}
merge(
accounts,
balances.pipe(map(a => ({ id: a.account_id, balance: a.balance })))
)
.pipe(
scan((result: Outcome[], incomming) => {
const found = result.find(row => row.id === incomming.id);
if (found) {
Object.assign(found, incomming);
} else {
result.push(incomming);
}
return result;
}, []),
tap(r => console.log(r))
)
.subscribe();
Please note that the result is a hot observable. If you only want to emit a single result and complete when all results are in, replace the scan
operator with the reduce
operator.
The source is based on RXjs version 6. your imports might differ a bit on older versions.