Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditionally apply pipe operators

Tags:

angular

rxjs

I need a timeout operator to throw an error when parameter isTimeoutNeeded is True, so that I could handle the case if the subscribed observable do not emit any value after X seconds.

if (isTimeoutNeeded) {
    this.service.getData()
      .pipe(
          timeout(10000),
          ...
      )
      .subscribe((...) => ...);
} else {
    this.service.getData()
    .pipe( 
       ... 
    )    
    .subscribe((...) => ...);
}

Is it possible to write this in a rxjs way by conditionally adding timeout operator when needed?

I have tried using iif and switchMap but it did not work.

 this.service.getData()
    .pipe(
       mergeMap((response) =>
          iif(() => !isTimeoutNeeded,
          of(response),
          of(response).pipe(timeout(10000)) // did not apply timeout if isTimeoutNeeded = True
       )
    )
    .subscribe((...) => ...);

switchMap

 this.service.getData()
    .pipe(
           switchMap((response) => {
                if (!isTimeoutNeeded) {
                    return of(response);
                }
                return of(response).timeout(10000); // did not apply timeout if isTimeoutNeeded = True
            })
            .....
       )
    )
    .subscribe((...) => ...);
like image 715
Zainu Avatar asked Jun 17 '19 05:06

Zainu


1 Answers

RXJS works best when the operators easily describe the behavior without detailing the implementation. When you start using switchMap() and conditions to express a behavior the intent gets lost, and the code becomes difficult to maintain.

So just write your own operator.

function timeoutWhen<T>(cond: boolean, value: number): OperatorFunction<T, T> {
   return function(source: Observable<T>): Observable<T> {
       return cond ? source.pipe(timeout(value)) : source;
   }
}

Now when you use that operator the source code is easy to read and understand.

    this.service.getData().pipe(
       timeoutWhen(isTimeoutNeeded, 10000),
       ...
    ).subscribe((...) => ...);

Now you have something that is reusable and makes your observables easier to read and understand.

like image 128
Reactgular Avatar answered Sep 21 '22 04:09

Reactgular