RxJS

repository·master·Indexed 12 days ago

https://github.com/ReactiveX/rxjs

A library for composing asynchronous and event-based programs using Observables. Current development focuses on RxJS 9, transitioning to a platform-native architecture using web-standard Observables and Symbol-keyed operators. Includes the @rxjs/migrate CLI for deterministic source-migration from RxJS 7.

Tokens
253.9K
Snippets
292
Records
573
Agent score
99%

What's inside RxJS

  1. Overview of the RxJS Next project

    master

    RxJS Next is the development foundation for the platform-observable branch of RxJS. It is an exploratory implementation targeting a future major version (likely RxJS 9). The project focuses on aligning RxJS with platform-observable semantics and web standards.

    Key documentation areas include:

    • Architecture: Implementation details and target architecture.
    • Compatibility Strategy: How the project handles platform semantics, RxJS 7 behavior, and migration.
    • Symbol Operators: Explanations of Symbol-based operators, safe mutation, and pipeable compatibility.
    • Decision Logs: Records of accepted, proposed, and deferred architectural decisions.
  2. Understand the RxJS Next development roadmap and phases

    master

    The RxJS Next project plan outlines a multi-phase evolution focused on architectural safety, migration reliability, and AI-agent enablement. The roadmap progresses through several key stages:

    • Phase 0 (Foundation): Establishing architectural safety rails, including migration prototypes, package/install decisions, buildable packages, and lifecycle/import harnesses.
    • Phase 1 (Conformance): Focusing on Web Platform Test (WPT) harness attestation and strict conformance.
    • Phase 2 (Extension Kernel): Developing the core kernel for extensions.
    • Phase 3 (Operator Restoration): Restoring the operator API surface.
    • Phase 4 (API Contracts): Establishing intentional API and migration contracts.
    • Phase 5 (Migration & AI): Enabling migration workflows and AI-driven code transformations.
    • Phase 6 (Release): Final release phase.

    Note that specific operator priority lists and release dates are currently out of scope.

  3. Identify RxJS Next core packages

    master

    The RxJS Next architecture is built upon several key packages. Understanding their roles helps in managing dependencies and knowing where to look for specific functionality:

    • @rxjs/observable-polyfill: Supplies a conforming fallback for the ambient platform-shaped Observable, Subscriber, and native-style methods when a native Observable is not present in the runtime.
    • rxjs: The main extension library. It installs entry-scoped Symbol operators, factories, and async-iteration adapters via direct Symbol assignment. It also exports intentional RxJS APIs like Subjects and producer-per-subscription primitives.
    • @rxjs/migrate: A migration toolset that provides a deterministic engine and a portable 'Skill' for moving from RxJS 7. This is not a runtime dependency.
    • @rxjs/test (planned/future): An implementation-neutral testing framework that consumes an active realm Observable.
  4. What is an Observer and how to use it

    master

    An Observer is a consumer of values delivered by an Observable. It is a collection of callbacks that handle the three types of notifications an Observable can emit: next, error, and complete.

    To use an Observer, pass it as an argument to the subscribe method of an Observable.

    Observers can be partial. If you omit one of the callbacks (such as error or complete), the Observable will still execute normally, but the notifications corresponding to the missing callbacks will be ignored.

    const observer = {
      next: x => console.log('Observer got a next value: ' + x),
      error: err => console.error('Observer got an error: ' + err),
      complete: () => console.log('Observer got a complete notification'),
    };
    
    observable.subscribe(observer);
  5. What is a Subscription and how to use unsubscribe()

    master

    A Subscription is an object representing a disposable resource, typically the execution of an Observable. Its primary purpose is to allow you to stop an execution and release resources. To cancel an ongoing Observable execution, call the unsubscribe() method on the subscription object returned by .subscribe().

    import { interval } from 'rxjs';
    
    const observable = interval(1000);
    const subscription = observable.subscribe(x => console.log(x));
    
    // Later:
    // This cancels the ongoing Observable execution
    subscription.unsubscribe(); 
  6. What is an Observable?

    master

    An Observable is a lazy Push collection of multiple values. Unlike Pull systems (like Functions or Iterators) where the Consumer decides when to receive data, in a Push system like Observables, the Producer (the Observable) determines when to send data to the Consumer (the Observer).

    Key characteristics:

    • Lazy: The computation inside an Observable does not run until you subscribe to it.
    • Push-based: The Observable pushes values to the subscriber at its own pace.
    • Multiple Values: Unlike a Promise (which pushes a single value), an Observable can push zero, one, or many values over time, either synchronously or asynchronously.
    ProtocolSingle ValueMultiple Values
    PullFunctionIterator
    PushPromiseObservable
    import { Observable } from 'rxjs';
    
    const observable = new Observable((subscriber) => {
      subscriber.next(1);
      subscriber.next(2);
      subscriber.next(3);
      setTimeout(() => {
        subscriber.next(4);
        subscriber.complete();
      }, 1000);
    });
  7. What is a Subject and how to use it

    master

    An RxJS Subject is a special type of Observable that allows values to be multicasted to many Observers. Unlike plain Observables which are unicast (each subscriber gets an independent execution), a Subject maintains a registry of listeners and shares the same execution with all of them.

    Key characteristics:

    • Every Subject is an Observable: You can subscribe to it to receive values.
    • Every Subject is an Observer: It has next(v), error(e), and complete() methods. You can feed values into it by calling next().
    • Multicasting: You can use a Subject to convert a unicast Observable into a multicast one by passing the subject as an argument to an Observable's subscribe method.
    import { Subject } from 'rxjs';
    
    const subject = new Subject<number>();
    
    subject.subscribe({
      next: (v) => console.log(`observerA: ${v}`),
    });
    subject.subscribe({
      next: (v) => console.log(`observerB: ${v}`),
    });
    
    subject.next(1);
    subject.next(2);
    
    // Logs:
    // observerA: 1
    // observerB: 1
    // observerA: 2
    // observerB: 2
  8. Overview of RxJS 9 Architecture

    master

    RxJS 9 is a platform-based generation of RxJS designed to work with the native web-platform Observable. Key architectural shifts include:

    • Native Integration: It uses the native web-platform Observable when available, installing a conforming fallback via @rxjs/observable-polyfill only when necessary.
    • Symbol-Keyed Extensions: Operators and factories are implemented as module-owned Symbols. This prevents RxJS from polluting the platform's Observable prototype with string-named methods.
    • Explicit Producer Contracts: It distinguishes between platform Observable behavior and producer-per-subscription behavior. Use ColdObservable when every direct subscription must trigger its own producer.
    • Cancellation: Built upon AbortSignal and the platform Subscriber lifecycle.
    • ESM-Only: The published JavaScript is ESM-only. Node.js environments can bridge require() to these ESM files.
  9. What is a Scheduler in RxJS?

    master

    A Scheduler controls when a subscription starts and when notifications are delivered. It consists of three core components:

    1. Data Structure: It manages how tasks are stored and queued (e.g., based on priority).
    2. Execution Context: It defines where and when a task runs (e.g., immediately, via setTimeout, process.nextTick, or requestAnimationFrame).
    3. (Virtual) Clock: It provides a notion of time via a now() method. Tasks scheduled on a specific scheduler adhere to that scheduler's clock, which is particularly useful for testing with virtual time schedulers to simulate time passing synchronously.

    Essentially, a Scheduler allows you to define the execution context in which an Observable delivers notifications to its Observer.

  10. Handle cancellation with AbortSignal

    master

    Subscriptions in RxJS 9 support the standard { signal: AbortSignal } option for cancellation.

    Lifecycle details:

    • Operators manage upstream work through the downstream Subscriber lifecycle.
    • Cancellation is distinct from completion.
    • Teardown functions and subscriber.addTeardown() participate in the same platform lifecycle.
  11. Use Symbol operators for RxJS capabilities

    master

    RxJS 9 uses module-owned exact Symbols for its operators to allow different versions to coexist without overwriting each other. To use an operator, you must import it from its specific subpath and access it on the Observable instance using bracket notation with the Symbol.

    Key distinction:

    • Platform contract: Uses standard string methods (e.g., observable.map(project)).
    • RxJS contract: Uses the Symbol (e.g., observable[map](project)).

    Importing rxjs does not replace the platform string methods; both forms remain available.

    import 'rxjs';
    import { filter } from 'rxjs/filter';
    import { map } from 'rxjs/map';
    import { switchMap } from 'rxjs/switch-map';
    
    // Using the RxJS Symbol operators
    const result = source[filter]((value) => value.active)[map]((value) => value.id);
    
    // Comparison with platform string methods
    observable.map(project); // platform contract
    observable[map](project); // RxJS contract
  12. How RxJS 9 uses the web-platform Observable

    master

    RxJS 9 is built on the web-platform Observable. Instead of shipping a competing identity, RxJS extends the active realm's native Observable.

    Key behaviors:

    • Precedence: If a native Observable is present in the environment, RxJS uses it. A fallback implementation (polyfill) is only used when the platform primitive is absent.
    • Method Resolution: String-named methods (e.g., Observable.prototype.map) follow the platform contract. If a native implementation exists, that implementation is used; otherwise, the conforming RxJS fallback is used.
    • Compatibility: Because RxJS 9 relies on the platform's shared, ref-counted producer lifecycle, some RxJS 7 behaviors that conflict with this model are moved to a separate compatibility library rather than being part of the core RxJS 9 platform contract.