joining two streams of observables in RxJs according to specific conditions

前端 未结 2 819
悲&欢浪女
悲&欢浪女 2021-02-09 14:37

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

2条回答
  •  栀梦
    栀梦 (楼主)
    2021-02-09 15:29

    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.

提交回复
热议问题