While working with rxjs
, there are plenty of operators that one can use within the .pipe
operator of an observable. Just take a look at the api reference here and you'll realize that rxjs
provides all the operators that you need for most cases.
However, what if you needed to write your custom operator to transform data the way you wanted, or tweak the captureError
operator to handle the error in a certain way and return something else in case an error happened.
In an application I was working on, for which I was using Sentry to handle any errors, I wanted to have the captureError
to send the error message to Sentry, and return fallback data in case an error happened.
import { captureException } from '@sentry/angular'import { BehaviorSubject, Observable, OperatorFunction, catchError, tap } from 'rxjs'
export function consume<T>(consumer: BehaviorSubject<T>, fallback$: Observable<T>): OperatorFunction<T, T> { return (source$: Observable<T>) => { return source$.pipe( catchError((error) => { captureException(error) return fallback$ }), tap(consumer), ) }}
Note that the rxjs
tap operator takes either an observer object. In our case, our consumer
is a Behavior Subject
which is also an observer.
The operator above is written in the form of a curried function, that accepts two initial inputs: consumer
- which in this case was a behavior subject that stores the current value in the observable stream, and fallback$
which is the data to return in case an error happens. If no error happens, the captureError
rxjs operator isn't called. In all cases, either the data from the observable stream or the fallback data is passed on to the consuming behavior Subject.
And there we have it! Our own custom RxJS operator 🧞♂️
Last modified on: Mon Oct 17 2022