Introduction

to

 RxJS

@namirsab [github | twitter]

Namir Sayed-Ahmad Baraza

namirsab@gmail.com

element.addEventListener('click', event => {
    if (event.x >= 100 && event.y >= 100) {
        const doubleCoordinates = {
            x: event.x * 2,
            y: event.y * 2
        };
        console.log('2x:', doubleCoordinates.x, ' 2y': doubleCoordinates.y);
    }
});

When you see this...

const clicks = [ { x: 10, y: 20}, ... ];

clicks
    .filter(click => click.x >= 100 && click.y >= 100)
    .map(click => { x: click.x * 2, y: click.y * 2 })
    .forEach(doubleCoordinates => { 
        console.log('2X': doubleCoordinates.x, ' 2Y':, doubleCoordinates.y);
    });

Don't you find this...

...somehow similar?

// For each click event
element.addEventListener('click', event => {
    // Filter it if does not pass a given predicate
    if (event.x >= 100 && event.y >= 100) {
        // Map it (Transform it)
        const doubleCoordinates = {
            x: event.x * 2,
            y: event.y * 2
        };
        // Do something with it
        console.log('2x:', doubleCoordinates.x, ' 2y': doubleCoordinates.y);
    }
});

Check the semantics!

They are not that different!

What If...

Events

Arrays

?

Thats

what
RxJS does!

Hallo!

Ok, but...

What is RxJS?

...is a set of libraries to compose asynchronous and event-based programs using observable collections and Array#extras style composition in JavaScript

Using RxJS, developers represent asynchronous data streams with Observables, query asynchronous data streams using our many operators, and parameterize the concurrency in the asynchronous data streams using Schedulers. Simply put, RxJS = Observables + Operators + Schedulers.

RxJS
is Lodash
for Events

Why RxJS?

  • Asynchronous programming in JS is just not comfortable ( callback hell )
doAsync(param, (result, error) => {
    if (!error) {
        doAnotherAync(result, (anotherResult, anotherError) => {
            if (!anotherError) {
                doSomething(anotherResult);
            }
            else {
                console.err(anotherError);
            }
        });
    }
    else {
        console.err(error);
    }
});

Why RxJS?

  • Promises make things cleaner
doAsync(param)
    .then(result => doAnotherAsync(result))
    .then(result => doSomething(result))
    .catch(error => console.err(error))
  • But...
  • Promoses are not cancellable
  • Promises are only good for single values

Why RxJS?

  • RxJs "is" an evolution of promises
  • It can handle multiple values (sequences or streams)
  • The are cancellable

Rx Core Concepts

  • Observables / Observers

  • Subscriptions

  • Operators

Observables

Arrays

  • Both represent a sequence of values

  • Arrays are sequences in space
  • Observables are sequences in time
  • You can think about them as streams of events

Click events happenning in time

There are many ways to create observables

  • from events

  • from callback style functions

  • from promises

  • from arrays of values

  • from  ranges

  • from scratch, to convert our asynchronous code to observables.

Examples

// From Event
const clicks = Rx.Observable.fromEvent(document, 'click');

// From Promise
const getJoke = Rx.Observable.fromPromise(
  fetch('https://api.icndb.com/jokes/random')
);

// From Callback
const fromCallback = Rx.Observable.bindCallback(fnWithCallbackAtLast);

// From Array
const fromArray = Rx.Observable.from([1,2,3,4]);

// From Range
const range = Rx.Observable.range(1,5);

From Scratch

const simpleObservable = Rx.Observable.create(observer => {
  let counter = 0;
  const handler = setInterval(() => {
    // Produce a random value
    observer.next(Math.random());
    counter++;
    if (counter === 6) {
      // Completes the sequence
      observer.complete();
    }
  }, 500);
  
  // Return an unsubscribe method so we can cancel
  return () => {
    clearInterval(handler);
  }
});

Our first Observer

const  subscription = simpleObservable
  .subscribe(
    randomNumber => console.log(randomNumber), // onNext,
    err => console.log('error'),
    () => console.log('Completed')
  );

We subscribe to an Observable passing an Observer

An observer is just a set of 3 functions:

  • next( value )
  • error( error)
  • complete()

Subscriptions

// When we call subscripe, we get a Subscription object
// which has an unsubscribe method
const  subscription = simpleObservable
  .subscribe(
    randomNumber => console.log(randomNumber), // onNext,
    err => console.log('error'),
    () => console.log('Completed')
  );

A subscription esentially has an unsubscribe function to release resources or cancel an Observable

subscription.unsubscribe();

Operators

Operators are just pure functions that create a new Observable based on the current one.

They are just like map, and filter in Arrays

Operators

Transformation Operators

Filtering Operators

  • map
  • scan (reduce)
  • concatMap
  • groupBy
  • pluck
  • window

Combination Operators

  • merge
  • zip
  • concatAll
  • combineAll
  • filter
  • debounce
  • throttle
  • first
  • last
  • take

An Observable looks like...

Demo Time!

Who is behind this?

Just a small company...

With some others, also small, using it

Pros/Cons

Pros

Cons

  • Dealing with Asynchronous code is easier and more reliable
  • The pattern is useful both for synchronous and asynchronous code
  • Implies using functional programming which ensures code will be much more testable due to use of pure functions.
  • Big learning curve
  • Implies changing paradigm
  • Number of operators is huge and understand what they do takes time
  • Libraries don't return Observables, so you need to convert  asynchronous code to Observables manually
  • Library size is quite big, around 400 kb

Bibliography  and Resources

Thank you for Listening!

and ask something, i'll try to answer! :D

RxJS

By Namir Sayed-Ahmad Baraza