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
RxJS
Introduction to RxJS
- 418