简体   繁体   中英

Rxjs: map each element in an array field from an observable of object with another observable

I have a method called getTransactionDetails(id:string), and it returns an Observable of TransactionDetails object

getTransactionDetails(id:string):Observable<TransactionDetails> 

The TransactionDetails object looks like this:

class TranscationDetails{
    id:string;
    accessCode: string;
    veggiesList: Array<Veggie>;
    meatList: Array<Meat>;
}

The Veggie object looks like this:

class Veggie{
    id: string;
    name: string;
}

I have another method called getVeggieSummary(veggieId: string), and it returns an Observable of VeggieSummary:

getVeggieSummary(veggiesId:string):Observable<VeggieSummary>

VeggieSummary looks like this

class VeggieSummary{
    id:string;
    name:string;
    color:string;
    kind:string;
}

I would like to call getTransactionDetails(1), and transform all the Veggies elements in the veggiesList to be VeggieSummary and return an VeggieSummary array.

This is what I have

getTransactionDetails(1)
.flatMap(transactionDetails=>
    transactionDetails.veggiesList
       .map(veggie=>getVeggieSummary(veggie.id)))
.subscribe(result=>
    console.log(result)
)

Currently, result is an Observable<VeggieSummary> and the inner observable is not even getting subscribed...

How can I have an Observable<VeggieSummary[]> with rxjs operators?

note: My app's angular version does not support pipe. The RxJS version is v5

Could you try wrapping the array with forkjoin to see if it fixes the issue? I think currently it is returning Observable<VeggieSummary>[]

getTransactionDetails(1)
.flatMap(transactionDetails=>
    forkJoin(transactionDetails.veggiesList
       .map(veggie=>getVeggieSummary(veggie.id))))
.subscribe(result=>
    console.log(result)
)

You just need to wrap the inner observable with forkJoin , this converts the Observable<VeggieSummary>[] to Observable<VeggieSummary[]>

    getTransactionDetails(1)
      .flatMap((transactionDetails) =>
        forkJoin(
          transactionDetails.veggiesList.map((veggie) =>
            getVeggieSummary(veggie.id)
          )
        )
      )
      .subscribe((result) => console.log(result));

with forkjoin, this works:

  getTransactionDetails(1)
  .flatMap((transactionDetails) =>
    forkJoin(
      transactionDetails.veggiesList.map((veggie) =>
        getVeggieSummary(veggie.id)
      )
    )
  )
  .subscribe((result) => console.log(result));

I found zip with the spread operator (...) also works:

   getTransactionDetails(1)
  .flatMap((transactionDetails) =>
    zip(
      ...transactionDetails.veggiesList.map((veggie) =>
        getVeggieSummary(veggie.id)
      )
    )
  )
  .subscribe((result) => console.log(result));

I learned that from another post.

But I am not sure which one to use, forkjoin or zip? Does it matter?

I also learned about rest operator/spread operator (...) from that post.

But I still don't quite understand fully how it works in this example.

I am not sure which one I am using, am I using the rest or spread operator?

and what is it equivalent?

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