skip to content

RxJS

2 roadmaps56 questionsupdated

RxJS is the observable library behind Angular's async APIs: creation functions, pipeable operators, subjects and schedulers. Interviewers probe operator choice, teardown and hot versus cold.

on this pageshow

guide

overview

~1 min

RxJS is a library for composing asynchronous and event-driven code as streams of values over time. Most frontend developers meet it through Angular, whose HTTP client, router and forms hand out observables, but it fits any JavaScript code that coordinates input, timers, sockets and requests. Interviewers use it to test whether you can reason about time: what starts work, what is still running after a view closes, and which of several near-identical operators encodes the behaviour you actually want. The hub follows the way code uses the library. [Observables and observers](/topics/fe-rxjs-observables) is the contract everything else builds on, and [stream creation functions](/topics/fe-rxjs-creation) turn values, promises, events and time into streams. [Pipeable operators](/topics/fe-rxjs-pipeable-operators) is the largest section: mapping, filtering, time-based throttling, flattening and joining several sources. [Subjects and multicasting](/topics/fe-rxjs-subjects) covers sharing one execution among many subscribers. [Catching errors and retrying](/topics/fe-rxjs-error-retry) and [unsubscribing and schedulers](/topics/fe-rxjs-schedulers) decide how a stream fails, when it stops and on which clock it runs. [Marble diagram tests](/topics/fe-rxjs-marble-testing) are how you prove any of that without waiting. Junior rounds stay close to the model: laziness, the comparison with promises, the difference between two similar operators. Middle and senior rounds become bug hunts: a leak that survives teardown, a stale search result, a shared stream that never releases its socket, a test that hangs. Learn the observable contract and subscription lifetime first, then the everyday operators, then flattening.

primer

### An observable is a recipe, not a result A plain observable does nothing until something subscribes, and every new subscription runs the recipe again from the start. That one fact explains the comparison with promises, the request that fires twice, and why hot versus cold, sharing and retrying behave as they do. ### Many values, then one ending An observer can receive any number of values, followed by at most one terminal signal: error or completion. After that the stream is finished for good. Many traps come from forgetting whether a source ever ends: an accumulator that stays silent, a join that waits forever, an error handler expected to resume. ### Every subscription owns resources Subscribing wires up listeners, timers, sockets or requests, and the subscription is the handle that releases them. Finite sources clean up on their own; endless ones hold on until something ends them. Leak questions come down to telling the two apart and choosing a declarative ending over manual bookkeeping. ### Operators are functions from stream to stream `pipe()` chains functions that each subscribe to what is upstream and return a new observable. Position in the chain is meaning, not style: the same operator moved two lines can fix a leak or cause one. ### Flattening is a concurrency policy When each value starts an inner stream — a request per keystroke, a save per click — the flattening operator decides what happens on overlap: cancel the old work, run both, queue the new, or ignore it. A good answer names the failure each choice brings under load. ### Time is an input Rate-limiting operators, timers and schedulers treat time as data. Whether a value leaves at the start of a window, at its end or after a quiet period separates operators that look alike, and the same abstraction lets tests swap in virtual time. ### Sharing is opt-in By default each subscriber gets its own execution. Subjects and the share operators let one execution feed many subscribers, and the questions then become what a late subscriber receives and when the shared source is allowed to stop.

Observable
A lazy description of a stream. Subscribing runs it and delivers values, then optionally an error or completion, to one observer.
Subscription
The handle returned by subscribe(). Calling unsubscribe() on it stops delivery and releases whatever the stream set up.
Teardown
The cleanup logic a stream registers when it starts, such as removing a listener or clearing a timer, run once when the subscription ends.
Cold observable
A stream whose producer is created per subscription, so each subscriber gets its own independent execution from the beginning.
Hot observable
A stream whose producer exists independently of any one subscriber, so subscribers share it and only see what happens after they join.
Pipeable operator
A function that takes an observable and returns a new one, chained inside pipe() to transform, filter, time or combine values.
Higher-order observable
An observable whose values are themselves observables, usually produced by mapping each value to a request or other inner stream.
Flattening
Subscribing to the inner streams of a higher-order observable and merging their values into one output, under a chosen overlap policy.
Subject
An object that is both observable and observer: values pushed into it are broadcast to every current subscriber.
BehaviorSubject
A subject that always holds a current value, starts with an initial one, and hands it to each new subscriber at once.
ReplaySubject
A subject that buffers recent values, limited by count and age, and replays them to each new subscriber before live values.
Scheduler
An object that decides when and in which execution context work runs: synchronously, as a microtask, on a timer or per animation frame.
Virtual time
A simulated clock used by the test scheduler, so time-based operators run instantly and deterministically in tests.

Follow one feature through the layers. A creation function turns something outside the library — an event, a timer, a promise — into an observable. Operators in `pipe()` reshape it, and where one value should start more work, a flattening operator subscribes to an inner stream and applies its overlap policy. Error handling sits where a failure should stop. A share operator decides whether each subscriber pays for its own execution. Finally something subscribes — a component, a template, a test — and something decides when that subscription ends; in Angular templates the async pipe does both. A polling price feed shows several of those decisions meeting in one chain: ```typescript const prices$ = timer(0, 30_000).pipe( exhaustMap(() => fetchPrices().pipe( retry({ count: 2, delay: 1_000 }), catchError(() => of(null)), // this poll fails, the feed lives on ), ), shareReplay({ bufferSize: 1, refCount: true }), ); ``` Each choice is one section of the hub. The timer comes from creation functions. The flattening operator keeps a slow response from overlapping the next tick. Retry and recovery live inside the inner stream, because an error that reached the timer would end the feed for everyone. The share at the end gives all subscribers one poll and one latest value, and the reference-counting option lets the timer stop once the last subscriber leaves. Marble tests verify all of it without waiting thirty seconds. Schedulers run underneath all of it. Most code never names one, but swapping the default — for animation frames, or virtual time in a test — changes when values arrive, not what the chain means.

  1. Observables and Observers →

    The contract every other section assumes: laziness, the three notifications, teardown and the comparison with promises.

  2. Pipeable Operators →

    How chaining works and the everyday operators for mapping, filtering and timing that most interview code uses.

  3. Higher-Order Flattening →

    The four overlap policies behind requests, saves and searches; the most frequent middle-level operator question.

  4. Unsubscribing & Schedulers →

    When a subscription ends, how leaks happen and how to stop them, then which clock work runs on.

  5. Subjects and Multicasting →

    Hot versus cold in practice: pushing values yourself, late subscribers and sharing one execution safely.

  6. Catching Errors & Retrying →

    Recovery after errors terminate a stream: replacement streams, retries with backoff, timeouts and cleanup.

  • Subscribing inside another subscribe callback instead of flattening: the inner subscriptions escape teardown and cancellation, and the overlap policy is never stated.

  • Reaching for mergeMap by default when user input triggers requests; name the overlap behaviour first — see Higher-Order Flattening.

  • Putting takeUntil early in the chain and assuming everything after it stops — see takeUntil placement.

  • Expecting catchError to resume the stream it caught: that source is finished, so a long-lived stream needs its recovery inside the inner observable.

  • Adding shareReplay to an endless source without deciding what happens when subscribers leave — see the refCount leak.

  • Treating from(promise) as lazy: the promise has already started, so repeat subscriptions share one result unless a factory runs per subscription.

  • Testing debounce or polling with real waits or ad-hoc fake timers, then chasing flaky tests — see Marble Diagram Tests.

This guide assumes RxJS 7. A lot of production code, tutorials and interviewers still carry habits from RxJS 6, so several questions turn on what 7 changed: - **Promise conversion.** `toPromise()` is deprecated in favour of `firstValueFrom` and `lastValueFrom`, which state which value they wait for. - **Multicasting.** The `multicast`, `publish` and `refCount` family is deprecated; `connectable`, `connect`, `share` with a configuration object and `shareReplay` cover the same ground. - **Operator names.** Pipeable joins that shared a name with a creation function gave way to `*With` variants such as `mergeWith`, and during the 7.x line operators became importable from the main `rxjs` entry point, not only `rxjs/operators`. - **Retry.** `retry` gained a configuration object, and `retryWhen` is deprecated in favour of it. Further back, RxJS 6 made pipeable operators the standard, replacing operators patched onto the observable prototype; chained `.map().filter()` code is from that older era. When an answer depends on version, say which one you mean.

RxJS is the JavaScript member of the ReactiveX family, so its vocabulary transfers to RxJava and its relatives. In the browser it competes with simpler tools, and interviewers expect you to say when it is worth its weight. - **Promises and async/await** fit a single future value; observables earn their cost with many values over time, cancellation and composition across time. - **Signals**, including Angular's, hold synchronous current state and track dependencies automatically; observables model events and asynchronous flows. Angular ships interop helpers between the two, and a common modern answer uses signals for view state and RxJS for event streams, requests and timing. - **State libraries** in the Angular world lean on it too: NgRx's classic store exposes observables and its side effects are written as streams, so operator fluency carries over. A defensible choice names the workload. Debounced search, polling, cancellable requests and joins of several live sources favour RxJS; a value read once or a flag the template displays often does not need it.

explore

report an issue with this guide →

questions

page 1 of 2

In RxJS, what is the difference between of([1, 2, 3]) and from([1, 2, 3]), and what inputs does from() accept?

level: juniorimportance: must knowfreq 70%

answer

  1. arguments versus contents
  2. one array value or three numbers
  3. ObservableInput
  4. promises, iterables, streams

basics

~20 s

of([1, 2, 3]) emits the array as one value; from([1, 2, 3]) emits 1, 2 and 3 separately. from() converts any ObservableInput - arrays, iterables, promises, async iterables, ReadableStreams or Observables - into an Observable.

solid answer

~40 s

`of(...values)` emits each **argument** as-is, then completes, so `of([1, 2, 3])` emits a single array value and `of(1, 2, 3)` emits three numbers. `from(input)` **unpacks** one input: `from([1, 2, 3])` emits 1, 2, 3 and completes. `from()` accepts any `ObservableInput`: an Observable (returned as-is), an object implementing `Symbol.observable`, an array or array-like (so a string emits its characters), a Promise or other thenable, an async iterable, an iterable such as a `Map` or generator, or a `ReadableStream`. Anything else throws a `TypeError` when `from()` is called. `of` and `from` over arrays or iterables emit synchronously during `subscribe()`; `from(promise)` emits later, when the promise resolves.

code

ts · 17 lines
ts
import { from, of } from 'rxjs';

of([1, 2, 3]).subscribe((v) => console.log('of:', v));
// of: [1, 2, 3]

from([1, 2, 3]).subscribe((v) => console.log('from:', v));
// from: 1
// from: 2
// from: 3

from(new Map([['a', 1]])).subscribe((v) => console.log('map entry:', v));
// map entry: ['a', 1]

from(Promise.resolve(42)).subscribe((v) => console.log('promise:', v));
console.log('after subscribe');
// after subscribe
// promise: 42

go deeper

for a junior

Recall that of emits its arguments and from unpacks one input, and give the array example both ways.

for a middle

List the ObservableInput kinds from() accepts, and say which ones emit synchronously and which emit when a promise resolves.

for a senior

Watch for code that relies on from(promise) being lazy, and for per-item logic silently receiving whole arrays because of() was used.

for a principal

Encourage APIs that accept ObservableInput rather than Observable only, so callers can pass arrays or promises without wrapping them.

## Two creation functions, two jobs RxJS's **creation functions** build an `Observable` from something that already exists. `of` and `from` are the two most used, and they are easy to confuse because both can take an array. - **`of(...values)`** treats each argument as one value. It emits the arguments in order, then completes. - **`from(input)`** takes a single input and converts it, **unpacking** whatever it contains. | Expression | Emits | Then | |---|---|---| | `of(1, 2, 3)` | `1`, `2`, `3` | complete | | `of([1, 2, 3])` | `[1, 2, 3]` (one value) | complete | | `from([1, 2, 3])` | `1`, `2`, `3` | complete | | `of()` | nothing | complete | | `from('abc')` | `'a'`, `'b'`, `'c'` | complete | Under the hood, `of` simply calls `from` on its argument list, which is why `of(1, 2, 3)` and `from([1, 2, 3])` behave the same. ## What from() accepts `from()` accepts the type RxJS calls **`ObservableInput`**. RxJS 7 checks the input in this order: 1. an RxJS `Observable` - returned unchanged; 2. an object implementing **`Symbol.observable`** (an interop observable from another library); 3. an **array-like** value - arrays, `arguments`, typed arrays and strings; 4. a **Promise** or any thenable - it emits the resolved value then completes, or errors on rejection; 5. an **async iterable** - such as an async generator; 6. an **iterable** - a `Set`, a `Map` (yielding `[key, value]` pairs) or a generator; 7. a **ReadableStream**-like object. If none of these match - a plain object, a number, `null` - `from()` throws a `TypeError` whose message reads "You provided ... where a stream was expected". The check happens when `from()` is **called**, not when the result is subscribed, so the error surfaces at the call site. The same `ObservableInput` type is what operators accept wherever they need an inner source, which is why a function that returns a Promise or an array can be used almost anywhere RxJS expects an Observable. ## Timing and completion Both functions **complete** once the input is exhausted, but they differ in when values arrive: - `of(...)`, `from(array)` and `from(iterable)` emit **synchronously**: every value and the completion are delivered before `subscribe()` returns. - `from(promise)` emits **asynchronously**, when the promise's reaction runs - even for a promise that has already resolved. - `from(asyncIterable)` and `from(readableStream)` emit asynchronously as items become available. The array loop also checks whether the subscriber has closed before each value, so an operator such as `take(2)` downstream stops a large array early instead of walking all of it. ## Common mistakes - Writing `of(items)` when the code needs one emission per item. The subscriber receives the whole array once, and per-item operators never see individual items. - Writing `from(items)` when the code needs the array as a single value - for example, when feeding a list into a stream of "current list" states. - Passing a plain object to `from()` and expecting its properties to be emitted. Objects are not iterable; use `from(Object.entries(obj))` instead. - Believing `from(promise)` makes the promise lazy. The promise has already started; `from` only adapts its result. Deferring the promise's creation is `defer`'s job. ## from() as a normaliser Because `from()` returns an RxJS `Observable` unchanged, it is cheap to call on something that might already be one. That makes it a handy normaliser at API boundaries: - a helper that accepts `ObservableInput<T>` can call `from(input)` once and then use operators, whatever the caller passed; - an Observable from another library that implements `Symbol.observable` is adapted into an RxJS one, so RxJS operators can be applied to it; - a callback that sometimes returns an array and sometimes a promise can be handled by the same code path. ## Deprecated forms to recognise Older code passes a scheduler as the last argument - `of(1, 2, 3, asyncScheduler)` or `from(array, scheduler)`. That argument is deprecated since RxJS 6.5 and scheduled for removal in v8; the replacement is `scheduled(input, scheduler)`. Explicit type arguments on `of<T>()` with no values are also deprecated. ## In an interview The one-line answer is "`of` emits its arguments, `from` unpacks its input". A strong candidate adds the list of `ObservableInput` types, notes that `from(promise)` is asynchronous while `of` and `from(array)` are synchronous, and knows that `from()` on an unsupported value throws immediately rather than erroring through the stream.

  • In RxJS, what happens if you call from() with a plain object such as { a: 1 }?
    It throws a `TypeError` immediately, at the `from()` call, because a plain object is not an `ObservableInput`: it is not array-like, not a thenable and not iterable. The message says an Observable, Promise, ReadableStream, Array, AsyncIterable or Iterable was expected. To stream its properties, pass `Object.entries(obj)` to `from()` instead.
  • In RxJS 7, how do you make of(1, 2, 3) emit asynchronously now that the scheduler argument is deprecated?
    Use `scheduled([1, 2, 3], asyncScheduler)`, which RxJS added as the replacement for the scheduler argument on `of` and `from`. Each value is then delivered through the scheduler instead of inside the `subscribe()` call. How the individual schedulers differ is a separate topic.

saying these in an interview costs you the question

  • of([1, 2, 3]) emits 1, 2 and 3 as separate values.
  • from() over a plain object emits each property.
  • from(promise) makes the promise lazy, so it starts on subscribe.
  • of and from always emit asynchronously.
  • from() on an unsupported value errors through the stream when subscribed.
open as a page

In RxJS, how does an Observable differ from a Promise in when work starts, how many values it delivers, and cancellation?

level: juniorimportance: must knowfreq 80%

basics

~20 s

An RxJS Observable is lazy: its producer runs only when subscribed, once per subscriber, and can deliver zero, one or many values synchronously or asynchronously. A Promise starts eagerly, settles once, and has no cancel; unsubscribe() stops an Observable's work.

open as a page

In RxJS, what does distinctUntilChanged() drop from a sensor stream, and why can the same reading still appear twice?

level: juniorimportance: must knowfreq 64%

basics

~20 s

distinctUntilChanged() drops a value only when it equals the last value it emitted, using === by default. It remembers one key, so 21, 21, 22, 21 becomes 21, 22, 21; distinct() is the operator that suppresses every earlier repeat.

open as a page

In RxJS, why should a typeahead search use switchMap rather than mergeMap to call the search API for each query?

level: juniorimportance: must knowfreq 76%

basics

~20 s

Search responses can return out of order. mergeMap forwards every response, so a slow reply for an old query can overwrite the newest results. switchMap unsubscribes the previous request when a new query arrives, so only the latest results arrive.

open as a page

In RxJS, how do debounceTime and throttleTime differ, and which fits autosave while typing versus a scroll-position tracker?

level: juniorimportance: must knowfreq 72%

basics

~20 s

debounceTime emits the latest value once the stream has been silent for the given time, which suits autosave after typing pauses. throttleTime emits a value, then ignores the source for a fixed window, which suits steady scroll updates.

open as a page

In RxJS, what is the difference between the map and tap operators, and why do side effects belong in tap?

level: juniorimportance: must knowfreq 70%

basics

~20 s

map replaces each value with its projection's result; tap runs a callback for each notification and passes the original value through, ignoring the callback's return. Side effects in tap keep map pure and visible in the pipe.

open as a page

In RxJS, when must you call unsubscribe() on a Subscription, and when does a subscription end on its own?

level: juniorimportance: must knowfreq 78%

basics

~10 s

An RxJS subscription ends on its own when the source completes or errors, which runs its teardown. Sources that never finish, such as interval, fromEvent or a long-lived Subject, need unsubscribe(), take(1) or takeUntil.

open as a page

In RxJS, how do interval(5000), timer(5000) and timer(0, 5000) differ, and which suits polling that must fire immediately?

level: middleimportance: must knowfreq 58%

basics

~20 s

interval(5000) emits 0, 1, 2... every 5 s, first after 5 s, forever. timer(5000) emits 0 once after 5 s and completes. timer(0, 5000) emits at once, asynchronously, then every 5 s - the usual choice for polling.

open as a page

In RxJS, what must a catchError selector return, and what does the subscriber see when it returns of(fallback), EMPTY or throwError?

level: middleimportance: must knowfreq 72%

basics

~20 s

catchError's selector must return an observable input that replaces the errored source: of(fallback) delivers the fallback then completes, EMPTY just completes, and throwError(() => err) passes a new or translated error on; the failed source never resumes.

open as a page

In RxJS, how would you wrap the browser's navigator.geolocation.watchPosition in an Observable so that unsubscribing stops the position watch?

level: middleimportance: must knowfreq 60%

basics

~10 s

Use new Observable(subscriber => ...): call watchPosition inside it, forward positions to subscriber.next and failures to subscriber.error, and return a teardown function that calls clearWatch with the stored watch id.

open as a page

In RxJS, how do combineLatest and forkJoin differ, and why can a forkJoin never emit when one source never completes?

level: middleimportance: must knowfreq 76%

basics

~20 s

combineLatest emits the latest value of every source once each has emitted, then again on every new value; forkJoin waits for every source to complete and emits their last values once, so a never-completing source blocks it forever.

open as a page

In RxJS, why does first() error with EmptyError when the source completes without a value, while take(1) simply completes?

level: middleimportance: must knowfreq 60%

basics

~20 s

first() promises one value: filter plus take(1) plus a check that errors with EmptyError if the source completes empty. take(1) promises at most one and just completes. first(pred, fallback) emits the fallback instead of erroring.

open as a page

In RxJS, how do switchMap, mergeMap, concatMap and exhaustMap differ when a new value arrives while an inner observable is still running?

level: middleimportance: must knowfreq 82%

basics

~20 s

switchMap unsubscribes the running inner observable and switches to the new one; mergeMap runs both at once; concatMap queues the new value until the current inner completes; exhaustMap ignores the new value until the current inner completes.

open as a page

In RxJS, what is the difference between scan and reduce, and which would you use for a live cart total?

level: middleimportance: must knowfreq 62%

basics

~20 s

scan emits the updated accumulator after every value; reduce emits only the final accumulator when the source completes. A live cart total needs scan, because the cart stream never completes and reduce would never emit.

open as a page

In RxJS, how does a BehaviorSubject differ from a plain Subject, and what does a late subscriber receive from each?

level: middleimportance: must knowfreq 80%

basics

~20 s

A plain Subject forwards only values pushed after you subscribe; a BehaviorSubject requires an initial value, always holds the latest one, emits it immediately to each new subscriber and exposes it synchronously through getValue() or value.

open as a page

In RxJS, a view tears down with takeUntil(destroy$), yet its polling keeps firing after it closes; why does takeUntil's position in the pipe matter?

level: seniorimportance: must knowfreq 55%

basics

~20 s

RxJS takeUntil completes only what is downstream of it and unsubscribes only its upstream. A flattening or combining operator placed after it waits for its still-active inner or other sources, so polling survives; put takeUntil last.

open as a page

In RxJS, what does fromEvent(button, 'click') do when you subscribe and unsubscribe, and when does the resulting stream complete?

level: juniorimportance: should knowfreq 55%

basics

~20 s

fromEvent adds a click listener to the button on each subscribe, emits every event object, and removes that listener on unsubscribe. It never completes on its own, so something must unsubscribe or a take-style operator must end it.

open as a page

In RxJS, what does retry(3) do when a request observable errors, and how is that different from catchError?

level: juniorimportance: should knowfreq 58%

basics

~10 s

retry(3) catches an error by resubscribing to the source, which re-runs a cold request up to three more times, then passes the last error on; catchError instead replaces the failed stream with another observable.

open as a page

In an RxJS marble diagram string such as '--a--b--|', what do the dashes, the letters, | and # represent?

level: juniorimportance: should knowfreq 30%

basics

~20 s

In RxJS marble diagrams each dash is one frame of virtual time, a letter or digit is a next value at that frame, | is completion and # is an error. In '--a--b--|', a emits at frame 2, b at 5, completion at 8.

open as a page

In RxJS, what is the difference between merge() and concat() when you combine two observables into one stream?

level: juniorimportance: should knowfreq 58%

basics

~10 s

merge subscribes to every source at once and forwards values as they arrive, interleaved; concat subscribes to the next source only after the previous one completes, so values come out source by source.

open as a page

In RxJS, given of(1, 2, 3, 4, 5, 1), what do take(3), takeWhile, skip(2) and skipWhile each emit with the predicate x < 3?

level: juniorimportance: should knowfreq 50%

basics

~20 s

take(3) emits 1, 2, 3 and completes; takeWhile(x => x < 3) emits 1, 2 and completes at the 3; skip(2) and skipWhile(x => x < 3) both emit 3, 4, 5, 1, since skipWhile stops checking once its predicate fails.

open as a page

In RxJS, what makes a Subject both an Observable and an Observer, and how does that let one source execution feed many subscribers?

level: juniorimportance: should knowfreq 55%

basics

~20 s

A Subject has subscribe() like an Observable and next(), error() and complete() like an Observer, keeping a list of subscribers; subscribing it to a source runs that source once and rebroadcasts every value to all of them.

open as a page

In RxJS, why does from(fetch(url)) not send a new request per subscription, and how does defer() change that?

level: middleimportance: should knowfreq 45%

basics

~20 s

fetch(url) starts the request as soon as the expression is evaluated, and from() only adapts that one promise, so every subscriber gets the same response. defer(() => fetch(url)) calls the factory on each subscribe, sending one request per subscription and none before.

open as a page

In RxJS, when does a finalize() callback run, and why is it more reliable than tap's complete handler for clearing a loading flag?

level: middleimportance: should knowfreq 45%

basics

~20 s

finalize runs whenever its subscription ends — on completion, error or unsubscription — while tap's complete handler runs only on completion, so a loading flag cleared there stays set after an error or a cancel.

open as a page

In an RxJS marble test, when do you create a source with hot() instead of cold(), and what does ^ mark?

level: middleimportance: should knowfreq 32%

basics

~20 s

In RxJS marble tests, cold() replays its timeline from each subscription, so it suits request stubs; hot() runs one shared timeline, so it suits user input or subjects. In a hot() diagram, ^ marks frame zero, where the tested code subscribes.

open as a page

In RxJS 7, why was Observable.toPromise() deprecated, and how do firstValueFrom and lastValueFrom behave on empty or endless streams?

level: middleimportance: should knowfreq 48%

basics

~20 s

toPromise() hid which value it returned and resolved undefined for an empty stream. firstValueFrom resolves on the first value and unsubscribes; lastValueFrom waits for completion. Both reject with EmptyError on an empty stream unless given defaultValue, and hang forever if nothing arrives.

open as a page

In RxJS, when exactly does the teardown returned from a new Observable subscriber function run, and what happens to next() calls afterwards?

level: middleimportance: should knowfreq 42%

basics

~20 s

RxJS runs the teardown once, on whichever comes first: unsubscribe(), error() or complete(); on error or complete it runs after the observer's callback. Afterwards the Subscriber is stopped, and later next, error or complete calls are silently ignored.

open as a page

In RxJS, when would you use withLatestFrom instead of combineLatest, and why can withLatestFrom silently drop source values?

level: middleimportance: should knowfreq 48%

basics

~10 s

Use withLatestFrom when only the source stream should trigger output and other streams just supply their latest value; source values that arrive before every other stream has emitted once are discarded, not queued.

open as a page

In RxJS, why does distinctUntilChanged() emit every sensor-reading object, and how do a comparator or distinctUntilKeyChanged() fix it?

level: middleimportance: should knowfreq 47%

basics

~20 s

Its default === compares object references, and each reading is a new object, so none look equal. Pass a comparator returning true for equal readings, a key selector as the second argument, or use distinctUntilKeyChanged('celsius') for one top-level property.

open as a page

showing 1–30 of 56