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.
