RxJS

https://github.com/ReactiveX/rxjs

What is RxJS?

  • Treating events as collections
  • Manipulating sets of events with operators

RxJS is like lodash for async

Async Events

  • DOM events
  • AJAX 
  • Web Sockets

Callbacks

Promise

Promises

  • Read-only view to a single future value
  • Success and error via .then()
  • Not lazy. By the time you have a promise, it's on its way to being resolved.
  • Immutable and uncancellable. Your promise will resolve or reject, and only once.

Observables

Observable

  • Streams
  • Of any number of things
  • Lazy
    • observable will not generate values via an underlying producer until they're subscribed to.
  • Can be unsubscribed from
    • underlying producer can be told to stop and tear down.

Click Events

const clickStream = Rx.Observable
                      .fromEvent(document.querySelector('.area'), 'click');
const throttledClickStream = clickStream.throttleTime(500/*ms*/);

clickStream

throttledClickStream

const bufferedStream = clickStream.buffer(throttledClickStream);

clickStream

throttledClickStream

bufferedStream

bufferedStream.map(array => array.length)

bufferedStream

bufferedStream.map(array => array.length)
              .filter(length => length >= 2);
const clickStream = Rx.Observable
                      .fromEvent(document.querySelector('.area'), 'click');

clickStream
  .buffer(clickStream.throttleTime(250))
  .map(array => array.length)
  .filter(length => length >= 2)
  .subscribe(e => {
      console.log('Hooray!');
  });

Code

Creating Observable

Text

// From one or multiple values
Rx.Observable.of('foo', 'bar');

// From array of values
Rx.Observable.from([1,2,3]);

// From an event
Rx.Observable.fromEvent(document.querySelector('button'), 'click');

// From a Promise
Rx.Observable.fromPromise(fetch('/users'));

// From a callback (last argument is a callback)
// fs.exists = (path, cb(exists))
var exists = Rx.Observable.bindCallback(fs.exists);
exists('file.txt').subscribe(exists => console.log('Does file exist?', exists));

// From a callback (last argument is a callback)
// fs.rename = (pathA, pathB, cb(err, result))
var rename = Rx.Observable.bindNodeCallback(fs.rename);
rename('file.txt', 'else.txt').subscribe(() => console.log('Renamed!'));

Operators

  • map, flatMap
  • find, findIndex, filter
  • first, last,
  • take, takeLast, takeUntil, takeWhile
  • skip, skipUntil, skipWhile
  • merge
  • throttle, throttleTime
  • debounce, debounceTime
  • ...

http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html

Drag and Drop

https://github.com/Reactive-Extensions/RxJS/tree/master/examples/dragndrop

var dragTarget = document.getElementById('dragTarget');

// Get the three major events
var mouseup   = Rx.Observable.fromEvent(dragTarget, 'mouseup');
var mousemove = Rx.Observable.fromEvent(document,   'mousemove');
var mousedown = Rx.Observable.fromEvent(dragTarget, 'mousedown');

var mousedrag = mousedown.flatMap(function (md) {

   // calculate offsets when mouse down
   var startX = md.offsetX, startY = md.offsetY;

   // Calculate delta with mousemove until mouseup
   return mousemove.map(function (mm) {
     mm.preventDefault();

     return {
       left: mm.clientX - startX,
       top: mm.clientY - startY
     };
  }).takeUntil(mouseup);
});

// Update position
var subscription = mousedrag.subscribe(function (pos) {
  dragTarget.style.top = pos.top + 'px';
  dragTarget.style.left = pos.left + 'px';
});

redux-observable

Epics

A function that takes a stream of all actions that dispatched and returns a stream of new actions to dispatch

Example

const pingPongEpic = (action$, store) =>
    action$.ofType('PING')
        .map(action => ({ type: 'PONG' }));

Example

const pingPongEpic = (action$, store) =>
    action$.ofType('PING')
        .delay(1000) // <--
        .map(action => ({ type: 'PONG' }));

Example

const autocompleteEpic = (action$, store) =>
    action$.ofType('QUERY')
        .filter(action => action.value.length > 2)
        .debounceTime(500)
        .distinctUntilChanged()
        .switchMap(action =>
            ajax('http://blahblah.com/?q='+action.value)
              .map(payload => ({
                type: 'QUERY_SUCCESS',
                payload,
              }))
              .takeUntil(action$.ofType('CANCEL_QUERY')
              .catch(payload => ({
                type: 'QUERY_FALIED',
                payload,
              }))
        );

Read More

  • RxJS In-Depth – Ben Lesh

    https://www.youtube.com/watch?v=KOOT7BArVHQ

  • Netflix JavaScript Talks - RxJS + Redux + React = Amazing!

    https://www.youtube.com/watch?v=AslncyG8whg

Tech Sharing 15 Sept

By Li Hau Tan

Tech Sharing 15 Sept

  • 462