How to use Observables within a method full of if-branching

Issue

Many times I faced this issue while trying to be more reactive, I am not able to find a clean way to do it, to make this method returns an Observable.

this is the example code:

public updateItemEligibility(item: Item): void
{
        this.updateCalculations(item);
        if (item.status == Status.Full)
        {
            this.markEligibleItem(item);
        }

        if (item.quantity > 0 && item.Stage == 1)
        {
           const info: ItemInfo =  this.getAdditionalInfoFromApi(); // will uses observable
           if (info.Staged)
           {
               this.updateStagedCalculations(item);
           }
        }

        if (item.quantity == 0 && item.Stage == 2)
        {
           const stagingInfo: StagingInfo =  this.getStaginInfoFromApi();
           item.eligible = this.allowStagedItems && item.amount > 0 && stagingInfo.Stages[item.stage].Completed == true;
        }
        this.updateTotals(item);
}

The problem here is calling the API only if a condition is satisfied.

Solution

If I understand your question right, you want a method that returns an Observable that notifies when the item is updated (if it has to be updated).

If this is the case, then I would proceed as follows (the comments try to explain the logic)

 public updateItemEligibility(item: Item): Observable<Item> {
    // this initial part is untouched since I guess is all synchronous stuff
    this.updateCalculations(item);
    if (item.status == Status.Full) {
      this.markEligibleItem(item);
    }
    // here we start the ifs.
    if (item.quantity > 0 && item.Stage == 1) {
      // In the first case we want to return an Observable
      // that notifies after getAdditionalInfoFromApi has returned
      // we use the map operator to make this Oservable notify with the item as value
      // after performing all necessary things
      return this.getAdditionalInfoFromApi().pipe(
        map((info: ItemInfo) => {
          if (info.Staged) {
            this.updateStagedCalculations(item);
            this.updateTotals(item);
            return item;
          }
        })
      );
    }
    // here the second if
    if (item.quantity == 0 && item.Stage == 2) {
      // as we have done above, we return an Observable that notifies when getStaginInfoFromApi returns
      // (assuming that getStaginInfoFromApi returns an Oservable) and we use map
      // to make the Observable notify with item as value
      return this.getStaginInfoFromApi().pipe(
        map((stagingInfo: StagingInfo) => {
          item.eligible =
            this.allowStagedItems &&
            item.amount > 0 &&
            stagingInfo.Stages[item.stage].Completed == true;
          this.updateTotals(item);
          return item;
        })
      );
    }
    // if none of the conditions above is met, we return an
    // an Observable that notifies immediately with item as value
    // using the of function
    this.updateTotals(item);
    return of(item);
  }
}

Answered By – Picci

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published