Conditionally apply pipe operators

You were almost right using switchMap:

const subject = new BehaviorSubject(this.service.getData());

subject
  .pipe(
    switchMap(response => {
      // If isTimeoutNeeded, a timetout is applied else wait result forever.
      return isTimeoutNeeded
        ? response.pipe(timeout(10000))
        : response;
    }),
    ...
  )
  .subscribe(... => ...);

In this code the timeout is applied on the getData observable whereas in your example it was a new observable.

Check my Stackblitz example.


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.


For this particular case, I did it like this:

.pipe(
  (isTimeoutNeeded? interval(5000) : identity)
)

Tags:

Angular

Rxjs