简体   繁体   中英

Angular RxJs Observable stream merge data

I'm trying to refactor my Angular code to be more "reactive"

I have data returned from an Observable which retreives account data account$ into an object for example:

{
 accountid: "123435", 
 name: 'bob', 
 customerId: "AR4533" 
 ..etc}

I also want to retreive payment data from another method call and merge it into the account object data:

{
 paymentId: "13434", 
 paymentName:"pay1" 
 ..etc}

The payment data needs a customerId parameter which is in the parent account data.

I've managed to pass this data through from the first observable using mergeMap however the resulting output is giving me the the payment data only, I want to have the account object with the payment data added within it as the output. Like so:

{
 accountid: "123435", 
 name: 'bob', 
 paymentData: {
    paymentId: "13434", 
    paymentName:"pay1" ..etc
   }
}
account$ = this.http.get<IAccountResponse>('account')
    .pipe(
      map(data => data.data),
      mergeMap(data => this.http.get<any>(`payment/subscription?customer=${data.stripe.customerId}`)),
      tap(data => console.log('PIPE:account', data))
    )

I know mergeMap does replace the data in the stream but is there a way to make the data merge into the current stream data object?

This can be solved by creating a closure :

account$ = this.http.get<IAccountResponse>('account')
    .pipe(
      map(data => data.data),
      mergeMap(
        data => this.http.get<any>(`payment/subscription?customer=${data.stripe.customerId}`).pipe(
          map(paymentData => ({ ...data, paymentData }))
        )
      ),
      tap(data => console.log('PIPE:account', data))
    )

I would use combineLatest in the mergeMap to get a handle on the accountData.

import { combineLatest, of } from 'rxjs';

account$ = his.http.get<IAccountResponse>('account')
    .pipe(
      map(data => data.data),
      mergeMap(data => combineLatest(
        of(data.data),
        this.http.get<any>(`payment/subscription?customer=${data.stripe.customerId}`),
      )),
      map(([accountData, customerData]) => {
        return {
          acountid: accountData.accountid,
          name: accountData.name,
          paymentData: {
            paymentId: customerData.paymentId,
            paymentName: customerData.paymentName,
          }
        };
      }),
      tap(data => console.log(data)),
    )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM