Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignore switchMap return value

Tags:

rxjs

I want to resolve an observable but I don't want the return value to replace the previous value in the pipe. Is there any asynchronous tap()? I need an operator like a switchMap but I want to ignore the return.

of(1).pipe(switchMap(() => of(2))).subscribe(console.log); // expected: 1

I could create a custom operator but sure there's something built-in in rxjs.

like image 763
Gabriel Llamas Avatar asked Feb 22 '18 22:02

Gabriel Llamas


People also ask

What does switchMap return?

SwitchMap switches to the most recent observable The SwitchMap operator returns an observable using the interval method. The interval method creates an infinite observable, which emits a sequence of integers spaced by a given time interval.

Does switchMap subscribe?

switchMap has only one active subscription at a time from which the values are passed down to an observer. Once the higher-order observable emits a new value, switchMap executes the function to get a new inner observable stream and switches the streams.

What is switchMap in RxJS?

RxJS switchMap() operator is a transformation operator that applies a project function on each source value of an Observable, which is later merged in the output Observable, and the value given is the most recent projected Observable.


2 Answers

I ended up with this custom operator. It is like tap but resolves observables (and should be updated to also support promises).

export function switchTap<T, R>(next: (x: T) => Observable<R>): MonoTypeOperatorFunction<T>;
export function switchTap<R>(observable: Observable<R>): MonoTypeOperatorFunction<R>;
export function switchTap<T, R>(
  arg: Observable<T> | ((x: T) => Observable<R>)
): MonoTypeOperatorFunction<T> {
  const next: (x: any) => Observable<T | R> =
    typeof arg === 'function' ? arg : (x: any): Observable<T> => arg;
  return switchMap<T, T>(value => next(value).pipe(ignoreElements(), concat(of(value))));
}

Usage:

of(1).pipe(switchTap(of(2))).subscribe(console.log) // 1

or with a function:

of(1)
      .pipe(
        switchTap(value => {
          console.log(value); // value: 1
          return of(value + 1);
        })
      )
      .subscribe(console.log); // 1
like image 178
Gabriel Llamas Avatar answered Jan 01 '23 12:01

Gabriel Llamas


If you just want to simply ignore the values of the subscribe, then just don't pass in any arguments in the subscribe callback:

of(1).pipe(switchMap(() => of(2))).subscribe(()=>{
    console.log('no arguments')
});

If you however want to retain the values of the first observable, things can get tricky. One way is to use Subject to retain the value:

//create a BehaviorSubject
var cache = new BehaviorSubject<any>(0);

of(1).pipe(switchMap((first) => {
    cache.next(first);
    return of(2);
})).subscribe(() => {
    console.log(cache.value) //gives 1
});

Or you can use .map() to alter the values. This is kind of hacky and the code is harder to maintain:

of(1).pipe(switchMap((first) => {
    return of(2).map(() => first);
})).subscribe((second) => {
    console.log(second) //gives 1 because the values was mapped
});
like image 41
CozyAzure Avatar answered Jan 01 '23 10:01

CozyAzure