Successfully reported this slideshow.
Your SlideShare is downloading. ×

RxJS Evolved

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 49 Ad

More Related Content

Slideshows for you (20)

Advertisement

Similar to RxJS Evolved (20)

Advertisement

RxJS Evolved

  1. 1. RXJS EVOLVED
  2. 2. PAUL TAYLOR @trxcllnt UI PLATFORM TEAM @
  3. 3. OBSERVABLE
  4. 4. EVENTEMITTER..... OBSERVABLE ≠ EVENTDISPATCHER EVENTDELEGATE...
  5. 5. “The idea of future values — maybe.” –ME
  6. 6. SINGLE MULTIPLE SYNCHRONOUS Function Enumerable ASYNCHRONOUS Promise Observable THE OTHER “IDEAS” OF VALUES
  7. 7. SINGLE MULTIPLE PULL Function Enumerable PUSH Promise Observable THE OTHER “IDEAS” OF VALUES
  8. 8. FUNCTIONS // The “idea” of a random number var getRandomNumber = function() { return Math.random(); } // A random number var rand = getRandomNumber.call(); (LAZINESS)
  9. 9. ANATOMY OF OBSERVABLE CREATION SUBSCRIPTION DISPOSAL
  10. 10. var randomNumbers = Observable.create((s) => { var i = setTimeout(() => { s.next(Math.random()); s.complete(); }, 1000); return () => clearTimeout(i); }); var sub = randomNumbers.subscribe({ next(x) { console.log(x); }, error(e) { console.error(e); }, complete() { console.log(“done”); } }); var randomNumbers = Observable.create((s) => { var i = setTimeout(() => { s.next(Math.random()); s.complete(); }, 1000); return () => clearTimeout(i); }); var randomNumbers = Observable.create((s) => { var i = setTimeout(() => { s.next(Math.random()); s.complete(); }, 1000); ANATOMY OF OBSERVABLE ★ CREATION ★ SUBSCRIPTION ★ DISPOSAL var randomNumbers = Observable.create(
  11. 11. WHAT HAPPENS WHEN… var randomNumbers = Observable.create((s) => { var i = setTimeout(() => { s.next(Math.random()); s.complete(); }, 1000); return () => clearTimeout(i); }); randomNumbers.subscribe(x => console.log(‘1: ’ + x)); randomNumbers.subscribe(x => console.log(‘2: ’ + x));
  12. 12. > > 1: 0.1231982301923192831231 > 2: 0.8178491823912837129834 > THIS HAPPENS
  13. 13. EVENTEMITTER..... OBSERVABLE ≠ EVENTDISPATCHER EVENTDELEGATE... OBSERVABLE = FUNCTION...........
  14. 14. “Observable is a function that, when invoked, returns 0-∞ values between now and the end of time.” –ME
  15. 15. OPERATORS
  16. 16. OPERATORS METHODS THAT PERFORM CALCULATIONS ON THE VALUES MAP, FILTER, SCAN, REDUCE, FLATMAP, ZIP, COMBINELATEST, TAKE, SKIP, TIMEINTERVAL, DELAY, DEBOUNCE, SAMPLE, THROTTLE, ETC.
  17. 17. “lodash for events” –NOT ME
  18. 18. WRITING AN OPERATOR (OLD) class Observable { constructor(subscribe) { this.subscribe = subscribe; } map(selector) { var source = this; return new Observable((destination) => { return source.subscribe({ next(x) { destination.next(selector(x)) }, error(e) { destination.error(e); }, complete() { destination.complete(); } }); }); } }
  19. 19. USING OPERATORS var grades = { “a”: 100, “b+”: 89, “c-“: 70 }; Observable.of(“a”, “b+”, “c-”) .map((grade) => grades[grade]) .filter((score) => score > grades[“b+”]) .count() .subscribe((scoreCount) => { console.log(scoreCount + “ students received A’s”); });
  20. 20. SCHEDULERS
  21. 21. SCHEDULERS CENTRALIZED DISPATCHERS TO CONTROL CONCURRENCY IMMEDIATE
 TIMEOUT
 REQUESTANIMATIONFRAME
  22. 22. USING SCHEDULERS Observable.range = function(start, length, scheduler) { return new Observable((subscriber) => { return scheduler.schedule(({ index, count }) => { if (subscriber.isUnsubscribed) { return; } else if (index >= end) { subscriber.complete(); } else { subscriber.next(count); this.schedule({ index: index + 1, count: count + 1 }); } }, { index: 0, count: start }); }); }
  23. 23. USING SCHEDULERS Observable.fromEvent(“mouseMove”, document.body) .throttle(1, Scheduler.requestAnimationFrame) .map(({ pageX, pageY }) => (<div className=“red-circle” style={{ top: pageX, left: pageY }} /> )) .subscribe((mouseDiv) => { React.render(mouseDiv, “#app-container”); });
  24. 24. RXJS NEXT (v5.0.0-alpha) github.com/ReactiveX/RxJS
  25. 25. CONTRIBUTORS BEN LESH ANDRÈ STALTZ OJ KWON
  26. 26. github.com/ReactiveX/RxJS/graphs/contributors
  27. 27. PRIMARY GOALS ★ MODULARITY ★ PERFORMANCE ★ DEBUGGING ★ EXTENSIBILITY ★ SIMPLER UNIT TESTS
  28. 28. import Observable from ‘@reactivex/rxjs/Observable’; import ArrayObservable from ‘@reactivex/rxjs/observables/ArrayObservable’; import reduce from ‘@reactivex/rxjs/operators/reduce’; Observable.of = ArrayObservable.of; Observable.prototype.reduce = reduce; Observable.of(1, 2, 3, 4, 5) .reduce((acc, i) => acc * i, 1) .subscribe((result) => console.log(result)); MODULARITY
  29. 29. SPEED 4.3X* FASTER
 *AVERAGE
 (UP TO 11X)
  30. 30. 50-90% FEWER ALLOCATIONS MEMORY
  31. 31. 10-90% SHORTER CALL STACKS DEBUGGING
  32. 32. DEBUGGING FLATMAP EXAMPLE RXJS 4
  33. 33. DEBUGGING FLATMAP EXAMPLE RXJS 5
  34. 34. DEBUGGING SWITCHMAP EXAMPLE RXJS 4
  35. 35. DEBUGGING SWITCHMAP EXAMPLE RXJS 5
  36. 36. PERFORMANCE + DEBUGGING ★ SCHEDULERS OVERHAUL ★ CLASS-BASED OPERATORS (“LIFT”) ★ UNIFIED OBSERVER + SUBSCRIPTION ★ FLATTENED DISPOSABLE TREE ★ REMOVE TRY-CATCH FROM INTERNALS
  37. 37. FLATMAP VS. LIFT flatMap<T, R>(selector: (value: T) => Observable<R>): Observable<R>; lift<T, R>(operator: (subscriber: Observer<T>) => Observer<R>): Observable<R>;
  38. 38. FLATMAP Observable.prototype.map = function map(project) { var source = this; return new Observable(function (observer) { return source.subscribe( (x) => observer.next(project(x)), (e) => observer.error(e), ( ) => observer.complete() ); }); } ★ CLOSURE SCOPE ★ INFLEXIBLE TYPE ★ CLOSURES SHOULD BE ON A PROTOTYPE
  39. 39. Observable.prototype.map = function(project) => { return this.lift(new MapOperator(project)); } class MapOperator implements Operator { constructor(project) { this.project = project; } call(observer) { return new MapSubscriber(observer, this.project); } } class MapSubscriber extends Subscriber { constructor(destination, project) { super(destination); this.project = project; } next(x) { this.destination.next(this.project(x)); } } ★ NO CLOSURES ★ DELEGATES NEW OBSERVABLE TO LIFT ★ USES SUBSCRIBER PROTOTYPE LIFT
  40. 40. EXTENSIBILITY ★ ALLOW SUBCLASSING OBSERVABLE ★ MAINTAIN SUBJECT BI-DIRECTIONALITY ★ FUTURE BACK-PRESSURE SUPPORT?
  41. 41. SUBCLASS OBSERVABLE class MouseObservable extends Observable { constructor(source, operator) { this.source = source; this.operator = operator || ((x) => x); } lift(operator) { return new MouseObservable(this, operator); } trackVelocity() { return this.lift((destination) => { return new VelocityScanningSubscriber(destination); }); } concatFrictionEvents(coefficientOfKineticFriction) { ... } }
  42. 42. SUBCLASS OBSERVABLE Observable.fromEvent(“mousedown”, document.body) .flatMap((downEvent) => { return Observable.fromEvent(“mousemove”, window) .let(_ => new MouseObservable(this)) .trackVelocity() .takeUntil(Observable.fromEvent(“mouseup”, window)) .concatFrictionEvents(0.5) }) .throttle(1, Schedulers.requestAnimationFrame) .subscribe(({ x, y }) => { item.style.top = y; item.style.left = x; });
  43. 43. MAINTAIN TWO-WAY SUBJECTS var naviSocket = new SocketSubject(“ws://127.0.0.1/navi”) .map(x => JSON.parse(x.data)) .throttle(100); naviSocket.subscribe((msg) => { if (msg == “hey, listen!”) { naviSocket.next(“go away navi!”); } });
  44. 44. SIMPLER UNIT TESTS MARBLE DIAGRAMS AS UNIT TESTS
  45. 45. SIMPLER UNIT TESTS MARBLE DIAGRAMS AS UNIT TESTS it('should filter out even values', function() { var source = hot('--0--1--2--3--4--|'); var expected = '-----1-----3-----|'; expectObservable(source.filter(x => x % 2 == 1)).toBe(expected); });
  46. 46. RXJS NEXT (v5.0.0-alpha) github.com/ReactiveX/RxJS

×