rxjsixjs

Difference between RxJS and IxJS?


What's the difference between RxJS and IxJS, and when would I want to use one over the other?

From the IxJS docs:

RxJS is great for event-based workflows where the data can be pushed at the rate of the producer, however, IxJS is great at I/O operations where you as the consumer can pull the data when you are ready.

After going through the docs, the only major difference seems to be the concept of Iterables in IxJS and Observables in RxJS.

Both Iterables and Observables execute either synchronously or asynchronously, and the .forEach from IxJS is essentially the same as RxJS's .subscribe method when paired with the almost-identical from creator function. The only other difference is IxJS's .forEach method is optional because you could use the imperative for-of instead.

It seems like there are two libraries for no reason because RxJS's from creator function can convert Iterables to Observables.

From my perspective, it's not really IxJS and RxJS, it's Iterables and Observables. How are they different and when would you use one over the other?


Solution

  • tl;dr

    RxJS processes values as soon as they arrive. It's a push system.

    IxJS specifies when to pass in the next value. It's a pull system.

    Explanation

    IxJS may be helpful if want to have pull-based model, for example, when dealing with backpressure.

    As you can see in the documentation:

    IxJS unifies both synchronous and asynchronous pull-based collections, just as RxJS unified the world of push-based collections. RxJS is great for event-based workflows where the data can be pushed at the rate of the producer, however, IxJS is great at I/O operations where you as the consumer can pull the data when you are ready.

    In other words:

    To understand what this means, consider the following example:

    You need to build ETL pipeline and process a large file (about 1TB).

    If you write it with RxJS, something like:

    readFileByLineObservable('path/to/file')
    .pipe(
      doSomeHeavyTransformation(),
    )
    .subscribe()
    

    Then readFileByLineObservable will try to "push" the entire file of 1TB into RAM as soon as possible. Only after this occurs, you will start to do doSomeHeavyTransformation. This problem is called backpressure.

    In contrast, IxJS will try to "pull" each newline only after previous line was processed. That's the optimal processing method in this case.

    The difference is how RxJS's .subscribe sets up a listener whereas IxJS's .forEach tells its iterator when to give the next value (only after its done processing the first one. It's similar to, but not the same as, RxJS's concatMap and concatAll operators.