Reputation: 1493
I am trying to avoid the following:
switchMap(([action, state]) =>
from(TodosDB.getAll()).pipe(
map(
(todos) => onQueryTodoDone({ items: todos }),
catchError((err) => of(onQueryTodoFail({ error: err })))
)
)
),
to something more linear like like we do with combineLatestFrom in ngrx. So far I tried to do the below. But the promise does not seem to work.
withLatestFrom(
from(TodosDB.getAll())
),
and
withLatestFrom(
from(TodosDB.getAll()).pipe(
map((todos) => onQueryTodoDone({ items: todos }))
)
)
Any ideas how to deal with this scenario without nesting pipe map in a switchMap?
PS: this might be obvious to you but I don't know much and I looked up on the internet and found withLatestFrom but not sure what I am missing.
EDIT: this is the best I got so far:
switchMap(([action, state]) =>
forkJoin([of(action), of(state), TodosDB.getAll()])
),
map(
([action, state, todos]) => onQueryTodoDone({ items: todos }),
catchError((err) => of(onQueryTodoFail({ error: err })))
),
The above is better but I have no idea if that can cause issues later. But hopefully I was able to communicate the idea. Which is append a promise result to the piped observable keep it's original structure
[Observable<Actions>,Observable<State>,Observable<FromPromise>]
Upvotes: 1
Views: 118
Reputation: 3393
Joining a few dots here and taking a bit of a guess I would say the problem stems from TodosDB.getAll
returning a Promise
.
With a promise based function you want to lazily evaluate it, as such a function is executed immediately when it is called, unlike an observable based function which requires a subscription.
This is why the switchMap
based solutions work, because the body of the switchMap
is not evaluated until the source emits.
In your shortened version using withLatestFrom
, there is no lazy evaluation, the getAll
call is probably evaluated once and once only when the effect is set up.
You can use the defer
operator to convert your promise based function to one that behaves more appropriately with the rxjs observable based operators.
withLatestFrom(defer(() => this.getAll())), // use of defer
map(([[action, state], todos]) => [action, state, todos]), // refine the shape of the data to your requirements
...
Note: The concatLatestFrom
ngrx operator also looks like it may be of use but I couldn't get it to work how I wanted.
Upvotes: 1