Created by Maximilian Schwarzmüller
    Last Updated on May 03, 2018

    # RxJS 6 Changes - Overview

    ** Watch the video above this article for a detailed walkthrough!**

    RxJS 6 is mostly used in Angular apps, and starting with Angular 6, it’s a mandatory dependency there. Learn more about the Angular 6 update here.

    RxJS 6 (or higher) introduces two important changes compared to RxJS version 5:

    1. Different internal structure that requires you to change your import statements
    2. pipe() as a method to chain your operators, the old way of chaining them will not work

    Additionally, some operators were renamed.

    Sounds horrible, right?

    Thankfully, you can make your old code work again by running just one command in your project folder:

    npm install --save rxjs-compat

    This command will install a package that ensures backward-compatibility of RxJS. Even though the rxjs package itself would not work with your current code, with the addition of rxjs-compat it will.

    Behind the scenes, rxjs still supports your old import statements and operator usage but it only does so if it can find the rxjs-compat package in the same project.

    Whilst this quick fix is of course nice to have and gives you time to do a proper update, the big question is:

    How do you properly update?

    # Import Statement Update Path

    With the release of version 6, RxJS changed its internal package structure. It did so to ensure that less code needs to be imported and that produced app bundles therefore are smaller. So this definitely is a good change.

    For the import statements, here’s how you have to update your code:

    # Observable, Subject etc.

    import { Observable } from 'rxjs/Observable'
    import { Subject } from 'rxjs/Subject'

    becomes

    import { Observable, Subject } from 'rxjs'

    # Operators

    import 'rxjs/add/operator/map'
    import 'rxjs/add/operator/take'

    becomes

    import { map, take } from 'rxjs/operators'

    # Methods to Create Observables

    import 'rxjs/add/observable/of'
    // or
    import { of } from 'rxjs/observable/of'

    becomes

    import { of } from 'rxjs'

    # Operators Update Path

    Operators like map are now used differently.

    In the past, you imported and used operators like this:

    import 'rxjs/add/operator/map'
    
    myObservable
      .map(data => data * 2)
      .subscribe(...);

    You already learned that the import path changed. But what do you do with this imported operator?

    import { map } from 'rxjs/operators'

    map is a function and it does exactly the same as the map method that was patched into the Observable prototype by the old import.

    But the map function alone doesn’t help you that much, you still need a way to connect it to your observable.

    # Using Operators in RxJS 6

    You use the newly introduced pipe() method for this (it was actually already added in RxJS 5.5).

    import { map } from 'rxjs/operators';
    
    myObservable
      .pipe(map(data => data * 2))
      .subscribe(...);

    pipe takes an infinite amount of arguments and each argument is an operator you want to apply to the Observable.

    So you could have a chain like this:

    import { map, switchMap, throttle } from 'rxjs/operators';
    
    myObservable
      .pipe(map(data => data * 2), switchMap(...), throttle(...))
      .subscribe(...);

    Needless to say that operators execute in the order you pass them into the pipe() method - left to right.

    # Renamed Operators

    You know the core adjustments you need to make: Different import paths and different operator usage.

    There’s one more important piece of information though: Some operators were renamed.

    This was necessary because of the new way you use them. For example, catch was fine as a chainable method name in RxJS 5.5 and lower but as a standalone function, you can’t use it. Why? Because catch is a reserved keyword in JavaScript.

    # The following operators were renamed

    • catch() => catchError()
    • do() => tap()
    • finally() => finalize()
    • switch() => switchAll()

    Additionally, some Observable-creation methods were renamed/ refactored:

    • throw() => throwError()
    • fromPromise() => from() (this automatically detects the type)