RxJS

Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences or Promises or array/iterable into one observable sequence.

A little bit of documentation

Returns an observable sequence which results from the comonadic bind operation.

Rx.observable.prototype.flatMap
Rx.observable.prototype.scan

The Reactive Extensions for JavaScript (RxJS) is
a set of libraries to compose asynchronous and event-based programs using observable collections and Array#extras style composition in JavaScript

Okay, what is RxJS?

What RxJS is not?

Not FRP (Functional Reactive Programming)

FRP deals with values that change continuously over time while ReactiveX deals with discrete values that are emitted over time.

What can we do with RxJS?

Reactive programming

reactive programming is a programming paradigm oriented around data flows and the propagation of change

Treat events as "streams" or sets

[clickEvent, clickEvent, clickEvent]

Manipulate sets of events with operators

[clickEvent, clickEvent, clickEvent]
  .map(e => e.screenX)
  .forEach(x => console.log(x));

What problems does RxJS solve?

Async-related "callback hell"

Due to lack of generators, continuation-style passing in JavaScript can be tricky, and error handling is a mess.

Async event order and scheduling

How to ensure that events arrive in order?

Lack of functional programming helpers

There're not many libraries (except perhaps BlueBird) that provide async-capable APIs with functional helpers similar to LoDash / Underscore / Ramda.

Haven't we solved async with Promises?

Promises are not cancellable

Consider an aborted XMLHTTPRequest. Promise-based AJAX implementations are unable to handle abort by design.

Promises are neither lazy, nor declarative

By the time you have a promise, it's already on its way to being resolved or rejected. There is no declarative way to describe an async operation.

Promises represent a single value

DOM events, WebSocket, server-sent events, and app life cycle events produce multiple values over time making it Promises a dubious fit.

No, not really.

What does RxJS offer to solve the problem?

Observable

The Observable object represents a push based collection.

Operators

Subject

Operators are chainable methods that create and operate on Observables.

A Subject is a sort of bridge that acts both as an observer and as an Observable.

Schedulers

A scheduler controls when a subscription starts and when notifications are published.

What's an Observable?

Observer
Pattern

Iterator
Pattern

Observable
sequence

Creating an observable

const source = Rx.Observable.create(observer => {
  // push some value to the observer:
  observer.onNext(42);
  observer.onNext(43);
  // inform observer that there will be no more events:
  observer.onCompleted();
  // provide a dispose function:
  return () => console.log('disposed');
});
const subscription = source.subscribe(
  value => console.log(`Got a value ${value}`),
  error => console.error(`Found an error ${error}`),
  () => console.log('Completed')
);

// "Got a value 42"
// "Got a value 43"
// "Completed"
subscription.dispose();

// "disposed"

Creating an observable using a helper

const source = Rx.Observable.just(42);

const subscription = source.subscribe(
  value => console.log(value),
  error => console.error(error),
  () => console.log('completed')
);

// 42
// "completed"
const source = Rx.Observable.range(0, 3);

const subscription = source.subscribe(
  value => console.log(value),
  error => console.error(error),
  () => console.log('completed')
);

// 0
// 1
// 2
// "completed"

Creating an observable from event source

function promiseFactory() {
  return Promise.resolve(42);
}

const source = Rx.Observable.fromPromise(promiseFactory());

const subscription = source.subscribe(
  value => console.log(value),
  error => console.error(error),
  () => console.log('completed')
);

// 42
// "completed"
const source = Rx.Observable.fromEvent(input, 'keyup');

const subscription = source.subscribe(
  value => console.log(value)
);

// [KeyboardEvent]
// [KeyboardEvent]
// ...

Using operators

const bestPlaceToWork = Rx.Observable.fromEvent(input, 'keyup')
  .pluck('target', 'value')
  .do(value => console.log(`Value is ${value}`))
  .filter(value => value === 'SFEIR')
  .map(company => `Best place to work is ${company}`)
  .take(1);
const subscription = bestPlaceToWork.subscribe(
  value => console.log(value),
  error => console.error(error),
  () => console.log('completed')
);
// "Value is S"
// "Value is SF"
// "Value is SFE"
// "Value is SFEI"
// "Value is SFEIR"
// "Best place to work is SFEIR"
// "completed"

Are RxJS operators the same as Array#extras?

Not really.

[1, 2, 3]
  .filter(x => x < 2)
  .map(x => x * 2);
Rx.Observable.from([1, 2, 3])
  .filter(x => x < 2)
  .map(x => x * 2);

Array#extras

RxJS operators

imperative style

everything is executed at once; needs to be wrapped in a function to be reusable

declarative style

nothing is executed until subscription;
reusable as is

performance issue

intermediate arrays have been created while calling operators

stream-like behavior

RxJS passes values through operators in the same way a stream passes data through pipes, without creating intermediate arrays

Example 1: timer

Example 2: counter

Example 3: let's drag!

RxJS v5 is coming soon

Questions?

RxJS

By Oleg Sklyanchuk