I'm having a problem where I'm returning an observable and sometimes inside that observable I should get a value from another observable. I simplified my problem to much simpler case but main problem is still there. Consider following code that works:
public dummyStream(): Observable<number> {
return of(true).pipe(
switchMap(isTrue =>
iif(() => isTrue === true,
combineLatest([of([1,2,3,4,5]), of(2)]).pipe(
map(([arrayOfNumbers, multiplier]) => {
const results = arrayOfNumbers.map(num => {
if (num !== 5) return num;
else return 4;
});
return results.reduce((prev, curr) => prev curr, 0);
})
),
combineLatest([of([1,2,3,4,5]), of(2)]).pipe(
map(([arrayOfNumbers, multiplier]) => {
return 0;
})
)
)
)
);
}
So little explanation. It all starts with of(true)
. For simplicity in this example it's always true so once we get to iif()
condition is always true.
Inside there I have combineLatest
that combines two observables. Then eventually I do arrayOfNumbers.map
and simply return that number again except in a case where number is 5 then I return 4.
Now what I'd like to do is to return of(num * multiplier)
but then of course return type from map
would by either number
or Observable<number>
and that's not working.
So this is same code but instead of returning number I'm returning Observable<number>
in else block
public dummyStream(): Observable<number> {
return of(true).pipe(
switchMap(isTrue =>
iif(() => isTrue === true,
combineLatest([of([1,2,3,4,5]), of(2)]).pipe(
map(([arrayOfNumbers, multiplier]) => {
const results = arrayOfNumbers.map(num => {
if (num !== 5) return num;
else of(num * multiplier);
});
return results.reduce((prev, curr) => prev curr, 0);
})
),
combineLatest([of([1,2,3,4,5]), of(2)]).pipe(
map(([arrayOfNumbers, multiplier]) => {
return 0;
})
)
)
)
);
}
Now how should I change this so that dummyStream()
return type would still be Observable<number>
but so that inside my else block I'm using another observable?
CodePudding user response:
I would restructure dummyStream
like this:
function dummyStream() {
return of(true).pipe(
switchMap(isTrue =>
iif(() => isTrue === true,
combineLatest([of([1,2,3,4,5]), of(2)]).pipe(
switchMap(([arrayOfNumbers, multiplier]) => {
return forkJoin(arrayOfNumbers.map(num => {
if (num !== 5) return of(num);
else return of(num * multiplier);
}));
}),
map((results) => results.reduce((prev, curr) => prev curr, 0))
),
combineLatest([of([1,2,3,4,5]), of(2)]).pipe(
map(([arrayOfNumbers, multiplier]) => {
return 0;
})
)
)
)
);
}
So instead of just return num
in the map, you return of(num)
so that you end up with an array of Observable<number>
. Change the outer map
to a switchMap
and wrap the resulting array in a forkJoin
to wait for all inner observables to finish. You can put the reduce
in its own map
afterwards.