RxJS and signal interoperability
RxJS models asynchronous streams with time, cancellation, and operators. Signals model current synchronous state. Angular applications often need both.
Flattening operators
switchMap: cancel obsolete work; good for search;concatMap: queue in order; good for serialized commands;exhaustMap: ignore new triggers while busy; useful for submit protection;mergeMap: run concurrently; bound concurrency when needed.
The operator encodes product behavior. Choose it deliberately.
Ownership
Prefer AsyncPipe, toSignal, or
takeUntilDestroyed to bind subscription lifetime to Angular
ownership. Nested subscriptions hide cancellation and error flow.
Subjects
Subjects are both producer and consumer. Use them for actual event bridges, not as mutable global state by default. BehaviorSubject offers a current value but can spread imperative writes.
Errors
An Observable normally terminates on error. Place
catchError at the boundary whose fallback is valid.
Returning an empty stream can silently remove critical data.
Sharing
shareReplay can cache and share, but its buffer,
reference-count, completion, and stale/error behavior must be
understood. It is not an application cache strategy by itself.
Interop strategy
Keep server event streams, websockets, and complex async workflows in RxJS. Expose stable current UI state as signals. Avoid converting back and forth at every method.
Feynman check
A signal answers “what is the value now?” An Observable answers “what values arrive over time?” Explain why a search result page may use both.