Llamo a dos funciones: fn1 y fn2 . Uso concatMap para invocar otro después del otro.
No uso exhustMap y switchMap porque conducen a un "infierno de devolución de llamada" anidado.
exhaustMap(() => fn1().pipe( switchMap(() => fn2())))) El único problema es cómo obtener los resultados de fn1 y fn2 en la next función que ocurre después de invocar fn2.
import { of } from 'rxjs'; import { concatMap, tap } from 'rxjs/operators'; console.clear(); const fn1 = () => { console.log('in fn1'); return of('fn1'); }; const fn2 = () => { console.log('in fn2'); return of('fn2'); }; of(1) .pipe( concatMap(() => fn1()), concatMap(() => fn2()), tap({ next: (a) => { console.log({ a }); /// <---- here I want to get fn1, fn2 from the functions. console.log('in tap!!!'); }, error: () => { console.log('in tap error!!!'); }, complete: () => { console.log('in tap complete'); }, }) ) .subscribe({ next: (r) => { console.log({ r }); }, error: (e) => { console.log({ e }); }, complete: () => { console.log('complete'); }, });No creo que haya un operador existente que pueda evitar el "infierno de los operadores", pero ¿quizás puedas construir uno que lo haga?
Algo como
import { from, ObservableInput, Observable } from "rxjs"; import { concatMap, map } from 'rxjs/operators'; const appendMap = <T, R extends ObservableInput<any>>(mapFn: (value: T) => R) => (source$: Observable<T>) => source$.pipe( concatMap((value) => from(mapFn(value)).pipe(map((result) => [value, result] as const)) ) );Entonces ahora puede usarlo y evitar "operadores-infierno":
import { of } from 'rxjs'; import { tap } from 'rxjs/operators'; const fn1 = () => of('fn1'); const fn2 = () => of('fn2'); of(1) .pipe( appendMap(() => fn1()), map(([_, fn1Result]) => fn1Result), appendMap(() => fn2()), tap({ next: ([fn1Result, fn2Result]) => { console.log({ fn1Result, fn2Result }); console.log('in tap!!!'); }, error: () => { console.log('in tap error!!!'); }, complete: () => { console.log('in tap complete'); }, }) ) .subscribe({ next: (r) => { console.log({ r }); }, error: (e) => { console.log({ e }); }, complete: () => { console.log('complete'); }, });Simplemente podría canalizar el segundo concatMap al concatMap fn1() y usar el map para emitir ambos valores.
of(1) .pipe( concatMap(() => fn1().pipe( concatMap((fn1Value) => fn2().pipe( map((fn2Value) => ({ fn1: fn1Value, fn2: fn2Value })) )) ) )He ajustado tu Stackblitz
Lo más cercano que se me ocurre está aquí: Stackblitz
const fn1$ = of(1); const fn2$ = of(2); fn1$.pipe( concatWith(fn2$) ).pipe( bufferCount(2) ).subscribe(console.log);