A reactive programming library for JavaScript

Overview

RxJS Logo RxJS: Reactive Extensions For JavaScript

CI npm version Join the chat at https://gitter.im/Reactive-Extensions/RxJS

RxJS 7 (beta)

FOR 6.X PLEASE GO TO THE 6.x BRANCH

Reactive Extensions Library for JavaScript. This is a rewrite of Reactive-Extensions/RxJS and is the latest production-ready version of RxJS. This rewrite is meant to have better performance, better modularity, better debuggable call stacks, while staying mostly backwards compatible, with some breaking changes that reduce the API surface.

Apache 2.0 License

Versions In This Repository

  • master - This is all of the current, unreleased work, which is against v7 of RxJS right now
  • stable - This is the branch for the latest version you'd get if you do npm install rxjs

Most PRs should be made to master.

Important

By contributing or commenting on issues in this repository, whether you've read them or not, you're agreeing to the Contributor Code of Conduct. Much like traffic laws, ignorance doesn't grant you immunity.

Installation and Usage

ES6 via npm

npm install rxjs

It's recommended to pull in the Observable creation methods you need directly from 'rxjs' as shown below with range. And you can pull in any operator you need from one spot, under 'rxjs/operators'.

import { range } from "rxjs";
import { map, filter } from "rxjs/operators";

range(1, 200)
  .pipe(
    filter(x => x % 2 === 1),
    map(x => x + x)
  )
  .subscribe(x => console.log(x));

CDN

For CDN, you can use unpkg:

https://unpkg.com/rxjs/bundles/rxjs.umd.min.js

The global namespace for rxjs is rxjs:

const { range } = rxjs;
const { map, filter } = rxjs.operators;

range(1, 200)
  .pipe(
    filter(x => x % 2 === 1),
    map(x => x + x)
  )
  .subscribe(x => console.log(x));

Goals

  • Smaller overall bundles sizes
  • Provide better performance than preceding versions of RxJS
  • To model/follow the Observable Spec Proposal to the observable
  • Provide more modular file structure in a variety of formats
  • Provide more debuggable call stacks than preceding versions of RxJS

Building/Testing

  • npm run compile build everything
  • npm test run tests
  • npm run dtslint run dtslint tests

Adding documentation

We appreciate all contributions to the documentation of any type. All of the information needed to get the docs app up and running locally as well as how to contribute can be found in the documentation directory.

Comments
  • publishBehavior and publishReplay semantics when completed

    publishBehavior and publishReplay semantics when completed

    Continuing the discussion that started here: https://github.com/ReactiveX/RxJS/pull/235/files

    RxJS Legacy (v4) passes these tests:

    var results1 = [];
    var results2 = [];
    var subscriptions = 0;
    
    var source = Rx.Observable.create(function (observer) {
      subscriptions++;
      observer.onNext(1);
      observer.onNext(2);
      observer.onNext(3);
      observer.onNext(4);
      observer.onCompleted();
    });
    
    var hot = source.shareValue(0);
    
    hot.subscribe(x => results1.push(x));
    
    expect(results1).toBe([0,1,2,3,4]);
    expect(results2).toBe([]);
    
    hot.subscribe(x => results2.push(x));
    
    expect(results1).toBe([0,1,2,3,4]);
    expect(results2).toBe([]);
    expect(subscriptions).toBe(2);
    

    and

    var results1 = [];
    var results2 = [];
    var subscriptions = 0;
    
    var source = Rx.Observable.create(function (observer) {
      subscriptions++;
      observer.onNext(1);
      observer.onNext(2);
      observer.onNext(3);
      observer.onNext(4);
      observer.onCompleted();
    });
    
    var hot = source.shareReplay(2);
    
    hot.subscribe(x => results1.push(x));
    
    expect(results1).toBe([1,2,3,4]);
    expect(results2).toBe([]);
    
    hot.subscribe(x => results2.push(x));
    
    expect(results1).toBe([1,2,3,4]);
    expect(results2).toBe([3,4]);
    expect(subscriptions).toBe(2);
    

    Yet RxJS Next behaves basically the opposite way:

    Failures:
    1) Observable.prototype.publishBehavior() should not emit next events to observer after completed
      Message:
        Expected [ 0 ] to equal [  ].
      Stack:
        Error: Expected [ 0 ] to equal [  ].
          at Object.<anonymous> (./RxJSNext/spec/operators/publishBehavior-spec.js:65:21)
    2) Observable.prototype.publishReplay() should emit replayed events to observer after completed
      Message:
        Expected [  ] to equal [ 3, 4 ].
      Stack:
        Error: Expected [  ] to equal [ 3, 4 ].
          at Object.<anonymous> (./RxJSNext/spec/operators/publishReplay-spec.js:98:21)
    145 specs, 2 failures
    Finished in 12.951 seconds
    

    Because in RxJS legacy there is

        ConnectableObservable.prototype._subscribe = function (o) {
          return this._subject.subscribe(o);
        };
    

    While in RxJS Next:

    class ConnectableObservable<T> extends Observable<T> {
      subject: Subject<T>;
    
      // ...
    
      _subscribe(subscriber) {
        return this._getSubject().subscribe(subscriber);
      }
    
      _getSubject() {
        const subject = this.subject;
        if (subject && !subject.isUnsubscribed) {
          return subject;
        }
        // Subject will be recreated
        return (this.subject = this.subjectFactory());
      }
    
      // ...
    }
    

    In my opinion, the new behavior in RxJS Next is illogical at first sight, and a potential source for a lot of developer confusion. Besides that, it differs from RxJS legacy features, making migration a potential headache. I think the semantics argument (with regard to subscriptions after complete(), publishReplay should behave just like a ReplaySubject and publishBehavior should behave just like a BehaviorSubject) is straightforward and also aligned with traditional Rx, such as in Rx.NET: check Lee Campbells book on this part.

    opened by staltz 70
  • RXJS own d.ts file error

    RXJS own d.ts file error

    node_modules/rxjs/BehaviorSubject.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/BehaviorSubject'. node_modules/rxjs/Observable.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/Observable'. node_modules/rxjs/Observer.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/Observer'. node_modules/rxjs/ReplaySubject.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/ReplaySubject'. node_modules/rxjs/Rx.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat'. node_modules/rxjs/Subject.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/Subject'. node_modules/rxjs/Subscriber.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/Subscriber'. node_modules/rxjs/Subscription.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/Subscription'. node_modules/rxjs/observable/forkJoin.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/observable/forkJoin'. node_modules/rxjs/observable/from.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/observable/from'. node_modules/rxjs/operators/map.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/operators/map'. node_modules/rxjs/operators/startWith.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/operators/startWith'.

    RxJS version:

    Code to reproduce:

    Expected behavior:

    Actual behavior:

    Additional information:

    opened by Son-Lam 60
  • feat(Zone): add support for Zone.js

    feat(Zone): add support for Zone.js

    Add support for Zone.js in a way which should have minimal impact on performance.

    Ensures that all callbacks are invoked in the same Zone as the Zone which was current at the time of the callback registration with the Rx.

    • Add getZone() method which returs always null if no Zone is present or returrns the current zone.
    • All places where the Zone needs to be intered are quarded to only go through zone if the Zone is different from the current Zone for performance reasons.
    opened by mhevery 59
  • TypeError: Observable.of is not a function since rxjs 6.3.0

    TypeError: Observable.of is not a function since rxjs 6.3.0

    After updating rxjs from version 6.2.x to version 6.3.0, the following:

    import 'rxjs/add/observable/of';
    // or 
    import { Observable } from 'rxjs/Observable';
    
    Observable.of(...)
    

    Are not working anymore. The only way to make it work now is by using:

    import { of } from 'rxjs/observable/of';
    
    of(...)
    

    is this a bug or the intended behaviour? It looks a breaking change to me :(

    opened by FrancescoBorzi 56
  • Error looking for rxjs/operators.js

    Error looking for rxjs/operators.js

    **RxJS version: 5.5.0 **

    Additional information: It looks like there is still one place using the old operators file (src/observable/dom/AjaxObservable.ts) line 7: import { map } from '../../operators';

    opened by bmkleine 55
  • Remove tryOrOnError from subscription

    Remove tryOrOnError from subscription

    Somehow we missed this, but in order to comply with the es-observable spec, and in order not to confuse RxJS 4 users more than we already have, errors thrown in the next handler shouldn't jump to the error handler:

    Observable.of('hi').subscribe(() => {
      throw 'haha!';
    }, (err) => {
      // THIS SHOULD NEVER BE HIT.
    });
    

    It should just throw.

    help wanted 
    opened by benlesh 53
  • The big reorganization PR for v6 (WIP)

    The big reorganization PR for v6 (WIP)

    See commit messages for more details.

    • Exports everything from top level rxjs.
    • Pipeable (lettable) operators import { map, filter, scan, switchMap } from 'rxjs';
    • Observable creation helpers import { timer, concat, fromEvent } from 'rxjs';
    • Removes operator versions of observable creation helpers (use concat(a, b, c) instead of a.pipe(concat(b, c)))
    • Starts moving things people should not be importing directly into an "internal" directory, so it's more obvious you're doing something silly.
    opened by benlesh 50
  • Subject::lift has incorrect type signature

    Subject::lift has incorrect type signature

    RxJS version: 5.3.0+

    Additional information:

    lift is defined on Observable<T> as:

    lift<R>(operator: Operator<T, R>): Observable<R>;
    

    Subject<T> defines lift with the signature:

    lift<R>(operator: Operator<T, R>): Observable<T>
    

    The return type should probably be Observable<R> rather than Observable<T>

    TS 
    opened by hearnden 49
  • manual typings for bindCallback.create

    manual typings for bindCallback.create

    Comparing against generation of types to spur on discussion of the best approach. I picked a single file here just as an example case. See #1087

    As a reference for TypeScript itself, these typings can't be simplified much more without losing the enhanced experience of operating against them.

    https://github.com/Microsoft/TypeScript/issues/5453 may be the answer, not sure if it answers all the possible use cases. It is currently on the road map for 2.0.

    I realize there will be tons of opinions my only goal is to make the TypeScript experience with RxJS5 as good as we have gotten the experience in RxJS4.

    opened by david-driscoll 47
  • backpressure story

    backpressure story

    opened by benlesh 46
  • STRAWMAN: pipe method

    STRAWMAN: pipe method

    Background

    There is a consistent problem with users using patch operators (rxjs/add/operator/map for example) and decoratiing the prototype, then having a consumer of their code depend on that map operator being there, without ensure that it is. This, in particular affects projects like Angular and Falcor (and I'm sure others).

    After talking with @IgorMinar about ways to solve this, a solution was proposed that's not much different than the op PR found here #2034. It does, however, look cleaner with a few exceptions.

    Proposal

    • adds a compose utility function to Rx. This is used to compose a rest args of functions into a single function like so:
    const double = (n: number) => n + n;
    const toString = (n: number) => '' + n;
    const toFixed = (size: number) =>  (n: number) => n.toFixed(size);
    const concat = (...append: string[]) => (s: string) => [s, ...append].join('');
    
    const composed = Rx.compose(double, toString, toFixed(2), concat('!!!'));
    
    composed(2); // "4.00!!!"
    composed(4); // "8.00!!!"
    
    • adds a pipe method to Observable. This pipe method will take a rest args of "pipeable operators", which are higher-order functions that return (source: Observable<T>) => Observable<R>. This, internally, uses the compose function above.
    • adds a Rx.Pipe.map and rxjs/pipe/map function that is a higher order function that returns a "pipeable operator". (used in the example above)

    Using Pipe:

    import { Observable } from 'rxjs/Observable';
    import { map } from 'rxjs/pipe/map';
    
    Observable.of(1, 2, 3)
      .pipe(
        map((x: number) => x + x),
        map((x: number) => x * x),
        map((x: number) => x + '!!!')
      )
      .subscribe(x => console.log(x));
    
    // "4!!!"
    // "16!!!"
    // "36!!!"
    

    vs the op/operate proposal:

    import { Observable } from 'rxjs/Observable';
    import { map } from 'rxjs/operator/map';
    
    Observable.of(1, 2, 3)
      .op(map, (x: number) => x + x)
      .op(map, (x: number) => x * x)
      .op(map, (x: number) => x + '!!!')
      .subscribe(x => console.log(x));
    
    // "4!!!"
    // "16!!!"
    // "36!!!"
    

    Pros

    1. Will allow fluent composition of Rx operators, including some functional programming goodness in combining them and dealing with them.
    2. Prevents prototype mutation and the problems there in
    3. It doesn't look that much different than using operators on the prototype (as opposed to the op/operate solution, which relies on comma separation.
    4. Less verbose than the op/operate solution.

    Cons

    1. It's a layer of indirection over top of what we already have
    2. We lose some type safety, because there isn't a great way to carry the type from one argument function that's passed topipe to the next.
    3. Yet another way to use operators.
    4. We'll need to wrap all of the existing operators as pipable.

    Other Things

    This PR adds the ability to compare two test observables via expectObservable(obs1).toBe(obs2). This was done to make it easier to test pipe operators as they are added.

    Using Rx.compose in unison with Observable.prototype.pipe is a fairly powerful combination, enabling a user to compose a chain of operations and reuse it much more dynamically than they might be able to otherwise.

    opened by benlesh 42
  • Timeout : throw error with Subject, even after data emitted by Subject

    Timeout : throw error with Subject, even after data emitted by Subject

    Describe the bug

    Following documentation, i expect that opertor "timeout" emit an Error only if no data has been emitted after a delay. With an operator like "of" or "interval", it works well. But with a Subject, even after a data is emited, the timeout will throw an Error.

    Expected behavior

    If the Subject emit something in the expected delay, there should not be any Error from the timeout operator

    Reproduction code

    No response

    Reproduction URL

    https://stackblitz.com/edit/rxjs-uwysqx?file=index.ts

    Version

    7.5

    Environment

    No response

    Additional context

    No response

    opened by Rebolon 0
  • TestScheduler can't be reused ? Doc is unclear.

    TestScheduler can't be reused ? Doc is unclear.

    Describe the bug

    I simplified my problem to this : I reuse a scheduler for multiple test, reading the doc I thought this would be ok.

    But unless I reset the frame at 0, the 2nd test will fail.

    Is this expected ? If so that might need a clarification on the marble testing doc.

    Anyway, thanks for the good work.

    Expected behavior

    Both test should pass without reseting the frame.

    Reproduction code

    const testScheduler = new TestScheduler((actual, expected) => {
      console.log(actual, expected, isEqual(actual, expected));
    });
    
    const test = (helpers: RunHelpers) => {
      const { cold, expectObservable } = helpers;
      const source = cold('---a--b--|');
      const expected = '   ---a--b--|';
      expectObservable(source).toBe(expected);
    };
    
    testScheduler.run(test);
    testScheduler.frame = 0; // 2nd test fails if removed
    testScheduler.run(test);
    

    Reproduction URL

    https://stackblitz.com/edit/rxjs-tucw4y?file=index.ts

    Version

    7.8

    opened by JeanMeche 0
  • chore: Use setup-node action to cache dependencies

    chore: Use setup-node action to cache dependencies

    Signed-off-by: jongwooo [email protected]

    Description

    Updated workflows to cache dependencies using actions/setup-node. setup-node@v3 or newer has caching built-in.

    AS-IS

    - uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node }}
    

    TO-BE

    - uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node }}
        cache: npm
    

    It’s literally a one line change to pass the cache: npm input parameter.

    References

    opened by jongwooo 0
  • expand oparator have wrong typing

    expand oparator have wrong typing

    Describe the bug

    Expand operator have wrong typings of project function. From the description it applies the projection function to every source value as well as every output value, so the project function should receive both – input and output types. But actually the types are implemented like this

    export function expand<T, O extends ObservableInput<unknown>>(
      project: (value: T, index: number) => O,
      concurrent = Infinity,
      scheduler?: SchedulerLike
    ): OperatorFunction<T, ObservedValueOf<O>>
    

    That means i can return another type from the project function and will not receive a compilation error.

    Expected behavior

    The type should be like this

    export function expand<T, O extends ObservableInput<unknown>>(
      project: (value: T | ObservedValueOf<O>, index: number) => O,
      concurrent = Infinity,
      scheduler?: SchedulerLike
    ): OperatorFunction<T, ObservedValueOf<O>>
    

    Reproduction code

    No response

    Reproduction URL

    No response

    Version

    7.6.0

    Environment

    No response

    Additional context

    No response

    opened by dilame 3
  • build(package): ensure NodeJS considers ESM .js files as ESM

    build(package): ensure NodeJS considers ESM .js files as ESM

    Description:

    NodeJS treats JavaScript files as ESM when one of the following is true:

    • The file is explicitly named .mjs
    • The file is part of a directory where the closest package.json has type: module.

    Both things are not applying for the ESM output in dist/esm and dist/esm5 so these ESM artifacts cannot be used directly in NodeJS because NodeJS will attempt loading them as CommonJS.

    Note that this was not noticeable with e.g. bundlers like Webpack as those do not rely on the NodeJS semantics for "detecting" ESM.

    Concrete issue:

    When you import rxjs from NodeJS from an ESM file, the loading of the RxJS files fails with syntax errors because NodeJS treats them as CommonJS.

    Related issue (if exists):

    #6321

    opened by devversion 0
Owner
ReactiveX
Reactive Extensions for Async Programming
ReactiveX
Ultra-high performance reactive programming

________________________________ ___ |/ /_ __ \_ ___/__ __/ __ /|_/ /_ / / /____ \__ / _ / / / / /_/ /____/ /_ / /_/ /_/ \____/__

The Javascript Architectural Toolkit 3.5k Dec 28, 2022
A reactive programming library for JavaScript

RxJS: Reactive Extensions For JavaScript RxJS 7 (beta) FOR 6.X PLEASE GO TO THE 6.x BRANCH Reactive Extensions Library for JavaScript. This is a rewri

ReactiveX 28.2k Dec 28, 2022
Functional reactive programming library for TypeScript and JavaScript

Bacon.js A functional reactive programming lib for TypeScript JavaScript, written in TypeScript. Turns your event spaghetti into clean and declarative

baconjs 6.4k Jan 1, 2023
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
Ultra-high performance reactive programming

________________________________ ___ |/ /_ __ \_ ___/__ __/ __ /|_/ /_ / / /____ \__ / _ / / / / /_/ /____/ /_ / /_/ /_/ \____/__

The Javascript Architectural Toolkit 3.5k Dec 28, 2022
A tiny, reactive JavaScript library for structured state and tabular data.

A JavaScript library for structured state. Using plain old JavaScript objects to manage data gets old very quickly. It's error-prone, tricky to track

tinyplex 1.4k Jan 1, 2023
Estrela - a JavaScript library for building reactive web components inspired by lit

Estrela ⭐ Full Reactive Web Components Estrela is a JavaScript library for building reactive web components inspired by lit. Just like Lit, Estrela is

null 50 Oct 31, 2022
This a programming training app, aimed to help OMRI's students learng the magic world of programming.

OMRI App (fe-omri-app) This a programming training app, aimed to help OMRI's students learng the magic world of programming. Install the dependencies

OMRI Tech 2 Nov 19, 2022
When a person that doesn't know how to create a programming language tries to create a programming language

Kochanowski Online Spróbuj Kochanowskiego bez konfiguracji projektu! https://mmusielik.xyz/projects/kochanowski Instalacja Stwórz nowy projekt przez n

Maciej Musielik 18 Dec 4, 2022
Cookbook Method is the process of learning a programming language by building up a repository of small programs that implement specific programming concepts.

CookBook - Hacktoberfest Find the book you want to read next! PRESENTED BY What is CookBook? A cookbook in the programming context is collection of ti

GDSC-NITH 16 Nov 17, 2022
Functional reactive UI library

reflex Reflex is a functional reactive UI library that is heavily inspired by (pretty much is a port of) elm and it's amazingly simple yet powerful ar

Mozilla 364 Oct 31, 2022
A functional and reactive JavaScript framework for predictable code

Cycle.js A functional and reactive JavaScript framework for predictable code Website | Packages | Contribute | Chat | Support Welcome Question Answer

Cycle.js 10.2k Jan 4, 2023
🍉 Reactive & asynchronous database for powerful React and React Native apps ⚡️

A reactive database framework Build powerful React and React Native apps that scale from hundreds to tens of thousands of records and remain fast ⚡️ W

Nozbe 8.8k Jan 5, 2023
Components for interactive scientific writing, reactive documents and explorable explanations.

@curvenote/article The goal of @curvenote/article is to provide web-components for interactive scientific writing, reactive documents and explorable e

curvenote 142 Dec 24, 2022
A tiny foundation for building reactive views

ripple.js A tiny foundation for building reactive views with plugins. It aims to have a similar API to Reactive, but allow composition of views, like

ripple.js 1.3k Dec 9, 2022
Marble.js - functional reactive Node.js framework for building server-side applications, based on TypeScript and RxJS.

Functional reactive Node.js framework for building server-side applications, based on TypeScript and RxJS. Ecosystem Name Description @marblejs/core F

Marble.js 2.1k Dec 16, 2022
Reactive Extensions for Angular

RxAngular offers a comprehensive toolset for handling fully reactive Angular applications with the main focus on runtime performance and template rendering.

RxAngular 1.5k Jan 5, 2023