Lessons46. Effects pattern: actions in, async work out
Lessons · 46
46. Effects pattern: actions in, async work out
What an effect is
If scan turns actions into state, an effect does something else: actions → side work (HTTP, a timer, a save) → new actions. This is the second half of the Redux/NgRx Effects pattern.
actions$.pipe(
filter(a => a.type === 'save'),
concatMap(a => api.save(a).pipe(map(() => ({ type: 'saved', id: a.id }))))
)
Why concatMap for saves
Saves must not be interleaved. Run two saves through mergeMap and, if the second finishes first, an old response could overwrite the newer state on the server. concatMap queues them — that's safe.
Your task
- In pipe, first
filter(action => action.type === 'save'). - Then, comma-separated,
concatMap(action => timer(20).pipe(map(() => ({ type: 'saved', id: action.id })))). - The
ignoreaction is filtered out, leaving two saves.
Deterministic check
This task's check runs in TestScheduler virtual time. If your solution is right, the console shows only Test Passed!. Don't add extra console.logs, or the check will fail.
Solution spoiler · click to reveal
const { Subject, timer, filter, concatMap, map } = Rx;
const actions$ = new Subject();
const effect$ = actions$.pipe(
filter(action => action.type === 'save'),
concatMap(action => {
return timer(20).pipe(
map(() => ({ type: 'saved', id: action.id }))
);
})
); script.ts
CONSOLE · Console output
Hit Run to see the result...