Tutorials Logic, IN info@tutorialslogic.com
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Website Development
Practice
All Practice Quiz Challenge Interview Questions Certification Practice
Tools
Online Compiler JSON Formatter Regex Tester CSS Unit Converter Color Picker
Compiler Tools
RxJS

RxJS Operators Guide with Examples

A practical RxJS guide focused on the most important operators, with beginner-friendly explanations, real use cases, Angular patterns, examples, traps, and practice questions.

Operators Observables Angular Examples Practice Questions

Published: Dec 2019 Updated: May 2026

Quick Summary

  • RxJS is: a library for working with values over time using Observables.
  • Operator means: a function that takes an Observable and returns a new Observable.
  • Use RxJS when: values arrive over time, can be cancelled, combined, filtered, retried, shared, or transformed.
  • Common examples: search input, button clicks, route changes, HTTP calls, WebSockets, timers, forms, and app state.
  • Biggest skill: choosing the right operator for the user experience.
Mental model: source Observable -> operators inside pipe() -> subscriber or async pipe.

Operator Categories

CategoryImportant operatorsPurpose
Creationof, from, fromEvent, interval, timer, defer, throwErrorCreate Observable sources.
Transformationmap, pluck, scan, reduce, bufferTime, pairwiseChange emitted values.
Filteringfilter, take, first, last, skip, distinctUntilChanged, debounceTime, throttleTimeControl which values pass through.
CombinationcombineLatest, withLatestFrom, forkJoin, zip, merge, concat, raceWork with multiple streams.
FlatteningswitchMap, mergeMap, concatMap, exhaustMapMap a value to another Observable and flatten the result.
Error and retrycatchError, retry, retryWhen, finalizeRecover, retry, and clean up.
Multicastingshare, shareReplay, publishShare subscriptions and cached values.

Creation Operators

OperatorExplanationExample use
ofCreates an Observable from fixed values.Return fallback data such as of([]).
fromCreates an Observable from array, promise, iterable, or similar source.Convert a Promise or array into a stream.
fromEventCreates a stream from DOM events.Listen to clicks, input, scroll, or keyup.
intervalEmits numbers repeatedly after a fixed interval.Polling, timer ticks, live counters.
timerEmits after a delay, optionally repeatedly.Delayed action or scheduled polling.
deferCreates a fresh Observable factory for each subscription.Run current-time logic only when subscribed.
throwErrorCreates an Observable that errors.Return an error from inside an operator.
Creation examples
import { of, from, fromEvent, interval, timer, defer } from 'rxjs';

of('Angular', 'React', 'Vue');
from(fetch('/api/users'));
fromEvent(document, 'click');
interval(1000);
timer(2000);
defer(() => of(new Date().toISOString()));

Transformation Operators

OperatorExplanationExample use
mapTransforms each emitted value.Convert API response into view model.
scanAccumulates state over time and emits each step.Counter, reducer-style state, running totals.
reduceAccumulates all values and emits once on completion.Final sum after finite stream completes.
pairwiseEmits previous and current value together.Compare route, scroll, or form changes.
bufferTimeCollects values for a time window.Batch frequent events.
toArrayCollects all values into an array when complete.Collect results from finite stream.
Transform user response
users$ = this.http.get<UserDto[]>('/api/users').pipe(
  map(users => users.map(user => ({
    id: user.id,
    label: `${user.firstName} ${user.lastName}`,
    active: user.status === 'ACTIVE'
  })))
);

Filtering and Rate-Control Operators

OperatorExplanationUse when
filterPasses values matching a condition.Ignore invalid form values.
takeTakes a fixed number of values, then completes.Read first 1 or first N values.
takeUntilCompletes when another Observable emits.Cleanup on destroy or cancellation signal.
firstEmits the first matching value.Need first valid event.
skipIgnores the first N values.Ignore initial default state.
distinctUntilChangedSkips same consecutive value.Do not repeat search for same term.
debounceTimeWaits for quiet time before emitting.Search box after typing stops.
throttleTimeEmits at most once per time window.Button click or scroll rate limiting.
auditTimeEmits latest value after each time window.UI updates during scroll/resize.
sampleTimeSamples latest value at intervals.Periodic snapshot of frequent events.
Search input stream

Combination Operators

OperatorExplanationBest use
combineLatestCombines latest values from multiple streams after each has emitted.View model from filters, sort, page, and data.
withLatestFromMain stream emits while sampling latest values from others.Button click uses latest form state.
forkJoinWaits for all inner Observables to complete, then emits final values.Parallel HTTP calls needed once.
zipPairs values by emission order.Step-by-step pair matching.
mergeRuns streams together and emits as values arrive.Combine multiple event sources.
concatRuns streams one after another.Sequence tasks in order.
raceUses the stream that emits first.Timeout or fastest source wins.
Build a view model
viewModel$ = combineLatest([
  users$,
  searchTerm$,
  selectedRole$
]).pipe(
  map(([users, term, role]) => ({
    users: users.filter(user =>
      user.name.includes(term) && (!role || user.role === role)
    ),
    term,
    role
  }))
);

Flattening Operators

OperatorBehaviorBest useAvoid when
switchMapCancels previous inner Observable and switches to latest.Search, route param HTTP calls, latest result wins.Every request must finish.
mergeMapRuns inner Observables concurrently.Independent writes, parallel requests, event fan-out.Order matters or concurrency must be limited.
concatMapQueues inner Observables and runs one at a time.Ordered saves, sequential jobs, queue behavior.Latest request should cancel old one.
exhaustMapIgnores new source values while inner Observable is active.Login, payment, submit button duplicate prevention.User should be able to cancel and start a newer request.
Submit button with exhaustMap
saveClicks$ = fromEvent(saveButton, 'click').pipe(
  exhaustMap(() => this.api.saveForm(this.form.value).pipe(
    catchError(error => {
      this.toast.error('Save failed');
      return EMPTY;
    })
  ))
);

Utility and Side-Effect Operators

OperatorExplanationExample use
tapRuns side effects without changing value.Logging, analytics, debugging.
delayDelays emissions.Demo loading, backoff sketch.
timeoutErrors if source takes too long.Fail slow request with fallback.
startWithEmits an initial value before source values.Initial loading or default UI state.
endWithEmits value after source completes.Completion marker.
defaultIfEmptyEmits fallback if source completes without value.No result fallback.
isEmptyEmits whether source had no values.Empty-state detection.

Error Handling Operators

OperatorExplanationImportant rule
catchErrorCatches an error and returns a replacement Observable.Always return an Observable.
retryRetries failed source a fixed number of times.Use only when retry is safe.
retryWhenCustom retry strategy using another stream.Useful for backoff logic.
finalizeRuns cleanup on complete, error, or unsubscribe.Good for loading flags.
HTTP error handling
users$ = this.http.get<User[]>('/api/users').pipe(
  retry({ count: 2, delay: 500 }),
  catchError(error => {
    this.logger.error(error);
    return of([]);
  }),
  finalize(() => this.loading.set(false))
);

Multicasting and Caching

ToolExplanationUse carefully
SubjectManual multicast source.Can become global mutable state.
BehaviorSubjectStores latest value and emits it to new subscribers.Good for current state.
ReplaySubjectReplays previous values.Always bound buffer size/time if possible.
shareShares one subscription while subscribers exist.Good for avoiding duplicated side effects.
shareReplayShares subscription and replays cached values.Use correct reset/refCount behavior to avoid stale cache.
Cache one HTTP result
profile$ = this.http.get<Profile>('/api/profile').pipe(
  shareReplay({ bufferSize: 1, refCount: true })
);

Angular Operator Patterns

  • Search field: map -> debounceTime -> distinctUntilChanged -> switchMap.
  • Route data: paramMap -> map -> switchMap.
  • Save button: click stream -> exhaustMap.
  • Ordered autosave: form value stream -> concatMap.
  • Dashboard view model: combineLatest of data, filters, and selected state.
  • Manual subscription cleanup: takeUntilDestroyed or framework lifecycle helper.
  • Template rendering: prefer async pipe instead of manual subscribe when possible.

Common Operator Mistakes

  • Using mergeMap for search, causing older responses to overwrite newer results.
  • Using switchMap for writes that must all complete.
  • Putting catchError at the end when only an inner request should recover.
  • Forgetting to return an Observable from catchError.
  • Using unbounded ReplaySubject and retaining too much memory.
  • Creating duplicate HTTP requests because a cold Observable is subscribed multiple times.
  • Hiding business logic in tap instead of keeping it explicit.
  • Manually subscribing in Angular when the async pipe would handle lifecycle.

25 Most Important Practice Questions

1. Which operator transforms each value?
Answer: map.
2. Which operator filters values by condition?
Answer: filter.
3. Which operator waits for typing to stop?
Answer: debounceTime.
4. Which operator skips repeated consecutive values?
Answer: distinctUntilChanged.
5. Which operator cancels old HTTP requests in search?
Answer: switchMap.
6. Which operator runs inner streams concurrently?
Answer: mergeMap.
7. Which operator queues async work in order?
Answer: concatMap.
8. Which operator ignores duplicate submits while one request is active?
Answer: exhaustMap.
9. Which operator combines latest values from multiple streams?
Answer: combineLatest.
10. Which operator waits for multiple HTTP requests to complete once?
Answer: forkJoin.
11. Which operator samples latest state when a button is clicked?
Answer: withLatestFrom.
12. Which operator runs side effects without changing values?
Answer: tap.
13. Which operator catches errors?
Answer: catchError.
14. What must catchError return?
Answer: An Observable, such as of([]) or throwError().
15. Which operator runs cleanup on complete, error, or unsubscribe?
Answer: finalize.
16. Which operator retries failed source?
Answer: retry.
17. Which operator provides custom retry strategy?
Answer: retryWhen.
18. Which operator emits an initial value?
Answer: startWith.
19. Which operator accumulates state over time?
Answer: scan.
20. Which operator compares previous and current value?
Answer: pairwise.
21. Which operator batches values by time?
Answer: bufferTime.
22. Which operator shares one subscription?
Answer: share.
23. Which operator shares and replays cached values?
Answer: shareReplay.
24. Which creation operator listens to DOM events?
Answer: fromEvent.
25. Which creation operator emits values every interval?
Answer: interval.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.