Home > Back-end >  How to have switchmap return values from earlier observable
How to have switchmap return values from earlier observable

Time:06-29

I have an observable that is getting customer info and I want then to use the customer number to look up the name

I need this.workDetail$ to contain both responses from getWorkItem which is a JSON object that may contain a customer number, if it does I want to look it up and add the customer name to the observable output

      this.workDetail$ = this.workService
        .getWorkItem(workNumber)
        .pipe(
          iif((res: WorkItemNumberResposne) => res.customerNumber),
              //want this customer number added to main output stream          
          this.customerService.getCustomerById(res.customerNumber),
            //else nothing to do
        );

if iif even the right way to do this?

CodePudding user response:

We could use switchMap https://www.learnrxjs.io/learn-rxjs/operators/transformation/switchmap operator to take value res from this.workService.getWorkItem(workNumber) and then switch to this.customerService.getCustomerById(res.customerNumber) which will be returned instead. We use iif() https://www.learnrxjs.io/learn-rxjs/operators/conditional/iif operator to compare, that res?.customerNumber != null || undefined and based on this condition we will return either trueResult or falseResult.

<p>Async Object</p>
<div *ngFor="let item of workDetail$ | async | keyvalue">
  {{ item.key }}:{{ item.value }}
</div>

<!-- 
id:1
item:something
name:Amber
-->
  detail = { id: 123, customerNumber: 1 };
  person = { id: 1, name: 'Amber', item: 'something' };

  workDetail$: Observable<any> = of(this.detail).pipe(
    switchMap((res) =>
      iif(() => res?.customerNumber != null || undefined, of(this.person), of(null))
    ),
    delay(1000)
  );

Feel free to make substitutions yourself and remove the delay.

Working example: https://stackblitz.com/edit/angular-ivy-8b33tr?file=src/app/app.component.ts

CodePudding user response:

iif return an observable or another one according to a condition. Your condition is about the response to an observable so we need use swichMap (you switch the observable "workDetail" to the observable "iif")

If condition is fullfilled you return the observable "this.customerService.getCustomerById(res.customerNumber)", but you transform (using map) to return an object with the properties of the fisrt observable plus the properties of this last Observable (for this I use spread operator, if only want to add a new property you can use some like {...res,customerName:customer.name}

In code

  workDetail$: Observable<any> = this.customerService.workDetail$.pipe(

   //we don't want this observable else the observable "iif"
    switchMap((res:any) => 

      iif(() => res.customerNumber,

          //if res.customerNumber, return the observable "getCustomerById"
           this.customerService.getCustomerById(res.customerNumber).pipe(

              //but "transformed"
              map((customer:any)=>({...res,...customer}))),

          //else simply return an observable using "of"
           of(res))
    )
  );
  • Related