I calling to two functions: fn1
and fn2
. I use concatMap
to invoke other after the other.
I don't use exhustMap
and switchMap
because they lead to nested "callback-hell".
exhaustMap(() =>
fn1().pipe(
switchMap(() => fn2()))))
The one problem is how to get the results of fn1
and fn2
into next
function that happens after fn2 is invoked?
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');
},
});
CodePudding user response:
You could just pipe in the 2nd concatMap
to the fn1()
and use map
to emit both the values.
of(1)
.pipe(
concatMap(() =>
fn1().pipe(
concatMap((fn1Value) => fn2().pipe(
map((fn2Value) => ({
fn1: fn1Value,
fn2: fn2Value
}))
))
)
)
I've adjusted your Stackblitz
CodePudding user response:
The closest I can think of is here: Stackblitz
const fn1$ = of(1);
const fn2$ = of(2);
fn1$.pipe(
concatWith(fn2$)
).pipe(
bufferCount(2)
).subscribe(console.log);
CodePudding user response:
import { of, zip } from 'rxjs';
import { concatMap, tap } from 'rxjs/operators';
console.clear();
const fn1$ = of('fn1');
const fn2$ = of('fn2');
zip(fn1$, fn2$)
.pipe(
tap({
next: (a) => {
console.log({ a }); // a === [fn1,fn2]
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');
},
});
CodePudding user response:
I don't think there's an existing operator that could avoid the "operators-hell", but maybe you can build one that would?
Something like
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))
)
);
So now you can use it and avoid "operators-hell":
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');
},
});