Here are some notes on the talk on RxJS Recipes by Dominic Elm and Kwinten Pisman.
Identifying Patterns
- What?: Result
- When?: Trigger
- How?: Pattern
Triggers and results should always be streams. If they are not streams, create streams yourself.
Repeater Pattern
Work that needs to be executed n times (n > 1)
const result$ = trigger$.pipe(<flatteningOperator>((_) => work$))
Enricher
Lazily enrich a stream with data when trigger fires
const result$ = trigger$.pipe(
withLatestFrom(enricherSource$),
map(([trigger, data]) => <data>),
);
Group Aggregator
Whenever the result is an Observable
const FT$ = falseTrigger$.pipe(mapTo(false))
const TT$ = trueTrigger$.pipe(mapTo(true))
const result$ = merge(FT$, TT$)
_(Note: While the merge _operator_ is deprecated, you can still use it as a creation function. If you want to use merge
in a pipe, use mergeWith instead.)_
State Management
Example: user settings that can be updated in a dialog.
const result$ = trigger$.pipe(
return((prevState, updates) => {
return {...prevState, ...updates}
})
)
Work Decider
Work that needs to be stopped and restarted when some trigger fires
const result$ = trigger$.pipe(<flatteningOperator>((condition) => {
if (condition) workA$
else workB$
}))
Use Observables as the boundaries between services and components.
Error Decider
Work that needs to be stopped and restarted when some trigger fires
const result$ = trigger$.pipe(
retryWhen((error$) => {
return error$.pipe(
switchMap((_) => {
if (condition) workA$
else workB$
})
)
})
)