Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Reactive java script mit rxjs basta! 2016

1.014 Aufrufe

Veröffentlicht am

Stellen Sie sich vor, das Iterator Pattern und das Observer Pattern lernen sich in einer Bar kennen, verlieben sich ineinander und zeugen ein Kind, das sie “RxJS” nennen. RxJS stellt Erweiterungen zur reaktiven Programmierung in JavaScript bereit. Es handelt sich hierbei um ein Paradigma, bei dem der Datenfluss im Fokus liegt. Angestrebt wird, ein stabiles, skalierbares und resilientes Anwendererlebnis zu schaffen. Im Kern steht der effiziente Umgang mit asynchronen Ereignissen. Und die sind zahlreich: vom Bootstraping der Applikation, Steuern von Animationen, Umgang mit Benutzereingaben bishin zu XHRs. Die Session erklärt anhand beispielhafter Implementierungen was hinter diesem Paradigma steht. Sie zeigt überdies auf, wie damit zeitgemäße asychrone Anwendungen eventgetrieben entwickelt werden ohne überflüssigen Overhead zu produzieren.

Note:
Viele Links in den Slides. Aber hier nochmal als Markdown:
https://github.com/ElectricMaxxx/Reactive-javascript-rxjs-talk/blob/master/slides/slides.md

Veröffentlicht in: Internet
  • Als Erste(r) kommentieren

Reactive java script mit rxjs basta! 2016

  1. 1. REACTIVE JAVASCRIPT MIT RXJS - BASTA! 2016 MAXIMILIAN BERGHOFF - 02.03.2016
  2. 2. Maximilian Berghoff @ElectricMaxxx github.com/electrimaxxx Mayflower GmbH - Würzburg Maximilian.Berghoff@mayflower.de
  3. 3. REACTIVE EXTENSIONS - RX
  4. 4. HISTORY ERIK MEIER BRAIN BACKMAN MATHEW PODWYSOCKI
  5. 5. LINQ TO EVENTS
  6. 6. VOLTA
  7. 7. WINDOWS FORMS <=> WEB FORMS
  8. 8. BEISPIEL: DRAG & DROP MAUSBEWEGUNG VERFOLGEN
  9. 9. EVENT LISTENER REGISTRIEREN elem.addEventListener('mousedown', mousedown, false);  elem.addEventListener('mouseup', mouseup, false);  elem.addEventListener('mousemove', mousemove, false); 
  10. 10. MOUSE DOWN function mousedown(e) {      isDown = true;      state = { startX: e.offsetX, startY: e.offsetY};  }
  11. 11. MOUSE MOVE function mousemove(e) {      if (!isDown) {return;}      var delta = {          endX: e.clientX ­ state.startX,          endY: e.clientY ­ state.startY      }; }
  12. 12. MOUSE UP function mouseup (e) {      isDown = false;      state = null;  }
  13. 13. UNSUBSCRIBE function dispose() {      elem.removeEventListener('mousedown', mousedown, false);      elem.removeEventListener('mouseup', mouseup, false);      elem.removeEventListener('mousemove', mousemove, false);  }
  14. 14. DIE AKTEURE
  15. 15. ITERATOR PATTERN
  16. 16. var Iterator = function () {};  Iterator.prototype.next();  Iterator.prototype.rewind();  Iterator.prototype.current();  Iterator.prototype.hasNext(); 
  17. 17. TRAVERSIEREN while (Iterator.hasNext()) {      console.log(Iterator.next());  }
  18. 18. GEDANKENSPIEL Liste von Cocktails Eigenschaften: id, name, zutaten, prozent, ... Aufgabe: "id & name von allem Contails mit prozent > 5.0"
  19. 19. var cocktails = [      {id: 100001, name: 'Piña Colada', zutaten: [], prozent: 5.0 },      { id: 100002, name: ' Tequila Sunrise', zutaten: [], prozent: 6.0 },     { id: 100003, name: ' Long Island', zutaten: [], prozent: 7.0 },  ];
  20. 20. var newList = [];  for(var i = 0; i <= cocktails.length; i++) {      if (cocktails[i].prozent > 5.0) {          newList.push({id: cocktails[i].id, title: cocktails[i].title})      } } console.log(newList); 
  21. 21. var newList = [];  cocktails.forEach(function (cocktail) {      if (cocktails[i].prozent > 5.0) {          newList.push({id: cocktail.id, title: cocktail.title})      } });
  22. 22. var godOnes = cocktails      .filter(function (cocktail) {        return cocktail.prozent > 5;    })   .map(function (cocktail) {        return {id: cocktail.id, name: cocktail.name};    });
  23. 23. OBSERVER PATTERN
  24. 24. Observable.prototype.subscribe() 
  25. 25. Observer.prototype.notify() 
  26. 26. var Observable = function () {};  Observable.prototype.subscribe = function () {};  Observable.prototype.unsubscribe = function () {};  var Observer = function () {};  Observer.prototype.notify = function() {}; 
  27. 27. WARUM? Entkopplung weniger prozedualer Code Erweiterbarkeit erhöht
  28. 28. DIE HOCHZEIT
  29. 29. By Ziko van Dijk (shot by myself) [ or ],GFDL CC BY-SA 3.0 via Wikimedia Commons REACTIVE EXTENSION RxJava RxJS Rx.Net Rx.Scala Rx.Clojure Rx.Swift ...
  30. 30. REACTIVEX.IO
  31. 31. GITHUB.COM/REACTIVE-EXTIONSION
  32. 32. STREAM VON EVENTS
  33. 33. var list = [1, 2, 3, 4, 5];  list.forEach(function (item) {      console.log("nexItem: %s", item);  });
  34. 34. var list = [1, 2, 3, 4, 5];  var source = Rx.Observable.fromArray(list);  var disposal = source.subscribe(      function (x) {console.log('Next: ' + x);},      function (err) {console.log('Error: ' + err);},      function () {console.log('Completed');});  disposal.dispose(); 
  35. 35. OBSERVER
  36. 36. By Vince Alongi (Flickr) [ ],CC BY 2.0 via Wikimedia Commons var disposal = source.subscribe(      function (x) {console.log('Next: ' + x);},      function (err) {console.log('Error: ' + err);},      function () {console.log('Completed');}  );
  37. 37. function Observer() { }  Observer.prototype.onNext = function (value) { ... };  Observer.prototype.onError = function (error) { ... };  Observer.prototype.onCompleted = function () { ... }; 
  38. 38. var source = Rx.Observable.range(1,10);  var reducedSource = source.filter(function (value) {      return value % 2 === 0;  }); var disposal1 = reducedSource.subscribe(      function (x) {console.log('Next 1: ' + x);},      function (err) {console.log('Error 1: ' + err);},      function () {console.log('Completed 1.');}  ); disposal1.dispose();  var disposal2 = source.subscribe(      function (x) {console.log('Next 2: ' + x);},      function (err) {console.log('Error 2: ' + err);},      function () {console.log('Completed 2');}  ); disposal2.dispose(); 
  39. 39. > Next 1: 2  > Next 1: 4  > Next 1: 6  > Next 1: 8  > Next 1: 10  > Completed 1.  > Next 2: 1  > Next 2: 2  > Next 2: 3  > Next 2: 4  > Next 2: 5  > Next 2: 6  > Next 2: 7  > Next 2: 8  > Next 2: 9  > Next 2: 10  > Completed 2 
  40. 40. OBSERVALBE
  41. 41. function Disposable() { }  Disposable.prototype.dispose = function () { ... }  function Observable() { }  /**  * @return Disposable   */ Observable.prototype.subscribe = function (observer) { ... } 
  42. 42. YOUTUBE
  43. 43. (ER-) ZEUGUNG
  44. 44. Rx.Observable.create() 
  45. 45. var source = Rx.Observable.create(function (observer) {    observer.onNext(42);    observer.onCompleted();    return function () {      console.log('disposed');    } }); var subscription = source.subscribe(    function (x) { console.log('onNext: %s', x); },    function (e) { console.log('onError: %s', e); },    function () { console.log('onCompleted'); }    ); subscription.dispose(); 
  46. 46. > onNext: 42  > onCompleted  > disposed 
  47. 47. Rx.Observable.range() 
  48. 48. var source = Rx.Observable.range(1, 5);  var subscription = source.subscribe(    function (x) { console.log('onNext: %s', x); },    function (e) { console.log('onError: %s', e); },    function () { console.log('onCompleted'); }  );
  49. 49. > onNext: 1  > onNext: 2  > onNext: 3  > onNext: 4  > onNext: 5 
  50. 50. Rx.Observable.fromEvent(element, eventName, [selector])  // oder Rx.Observable.fromCallback(func, [context], [selector]) 
  51. 51. var input = $('#input');  var source = Rx.Observable.fromEvent(input, 'keyup');  var subscription = source.subscribe(    function (x) {console.log('Next: key pressed!');},    function (err) {console.log('Error: %s', err);},    function () {console.log('Completed');}); 
  52. 52. var fs = require('fs'),      Rx = require('rx');  var exists = Rx.Observable.fromCallback(fs.exists);  var source = exists('file.txt');  var subscription = source.subscribe(      function (x) {console.log('Next: ' + x);},      function (err) {console.log('Error: ' + err);},      function () {console.log('Completed');}    );
  53. 53. LINQ LANGUAGE INTEGRATED QUERY
  54. 54. von Unbekannt [Public domain], via Wikimedia Commons KOMBINATION .concat();  // oder .merge(); 
  55. 55. var sourceOne = Rx.Observable.range(1,5);  var sourceTwo = Rx.Observable.range(6,5);  var merged = sourceOne.concat(sourceTwo);  var disposal = merged.subscribe(function (x) {      console.log('Concat onNext: ' + x);   });
  56. 56. OUTPUT > Concat onNext: 1  > Concat onNext: 2  > Concat onNext: 3  > Concat onNext: 4  > Concat onNext: 5  > Concat onNext: 6  > Concat onNext: 7  > Concat onNext: 8  > Concat onNext: 9  > Concat onNext: 10 
  57. 57. var sourceOne = Rx.Observable.range(1,5);  var sourceTwo = Rx.Observable.range(6,5);  var merged = sourceOne.merge(sourceTwo);  var disposal = merged.subscribe(function (x) {      console.log('Merged onNext: ' + x);   });
  58. 58. OUTPUT > Merged onNext: 1  > Merged onNext: 6  > Merged onNext: 2  > Merged onNext: 7  > Merged onNext: 3  > Merged onNext: 8  > Merged onNext: 4  > Merged onNext: 9  > Merged onNext: 5  > Merged onNext: 10 
  59. 59. FILTER
  60. 60. var source = Rx.Observable.range(1,10);  var filtered = source.filter(function (x) {      return x % 2 === 0;  }); var disposal = filtered.subscribe(function (x) {      console.log('onNext: ' + x);  });
  61. 61. OUTPUT > onNext: 2  > onNext: 4  > onNext: 6  > onNext: 8  > onNext: 10 
  62. 62. PROJEKTIONEN
  63. 63. var list = [      {id: 100001, name: 'Piña Colada', zutaten: [], prozent: 5.0 },      { id: 100002, name: ' Tequila Sunrise', zutaten: [], prozent: 6.0 },     { id: 100003, name: ' Long Island', zutaten: [], prozent: 7.0 },  ]; var source = Rx.Observable.from(list);  var ids = source.map(function (item) {      return item.id;  }); var disposal = ids.subscribe(function (x) {      console.log('onNext Id: ' + x);  }); disposal.dispose(); 
  64. 64. OUTPUT onNext Id: 100001  onNext Id: 100002  onNext Id: 100003 
  65. 65. ? .flatMap(); 
  66. 66. var source = Rx.Observable      .range(1, 2)      .flatMap(function (x) {          return Rx.Observable.range(x, 2);      }); var subscription = source.subscribe(      function (x) {          console.log('onNext: ' + x);      } );
  67. 67. return Rx.Observable.range(1, 2);  return Rx.Observable.range(2, 2); 
  68. 68. OUTPUT > onNext: 1  > onNext: 2  > onNext: 2  > onNext: 3 
  69. 69. NOCH MEHR? GITHUB/DOKUMENTATION
  70. 70. PROMISES? Single Value Cancellation?
  71. 71. ARRAY OPERATOREN VS. RX OPERATOREN
  72. 72. ARRAY OPERATOREN Komplette Liste wird durch gereicht dabei auf jedem Eintrag Projektion - map, .. Gefiltert - reduce, filter Ergänzt - concat, merge
  73. 73. RX OPERTOREN Jedes Event/Jeder Eintrag einzeln dabei Projektion - map, .. Gefiltert - reduce, filter Ergänzt - concat, merge Filter = STOP => nicht weiter gereicht Ergänzung nur der Zugang für weiteren Stream
  74. 74. ACTION
  75. 75. von Thiemo Schuff (Eigenes Werk) [ ],CC BY-SA 3.0 via Wikimedia Commons <input type="text" id="input"/>  <h2>Results</h2>  <ul id="results">  </ul>
  76. 76.     var $input = $('#input');      var $results = $('#results');      var suggestions = Rx.Observable.fromEvent($input, 'keyup'); 
  77. 77. var suggestions = Rx.Observable.fromEvent($input, 'keyup')          .pluck('target', 'value')          .filter(function(text) { return text.length > 2 })          .debounce(500 /* ms */)          .distinctUntilChanged(); 
  78. 78.     ...     flatMapLatest(function (term) {              return $.ajax({                  url: 'https://en.wikipedia.org/w/api.php',                  dataType: 'jsonp',                  data: {                      action: 'opensearch',                      format: 'json',                      search: term                  }              }).promise();          }); 
  79. 79.     ...     .subscribe(          function(data) {              $results                  .empty()                  .append($.map(data[1], function (value) {                      return $('<li>').text(value);                  }))          },          function(error) {              $results                  .empty()                  .append($('<li>'))                  .text('Error:' + error);          }      );
  80. 80. JS FIDDLE
  81. 81. By Musik- och teatermuseet (Own work) [ ],CC BY-SA 3.0 via Wikimedia Commons QUESTIONS? Ask Now! Twitter: @ElectricMaxxx Mail: Maximilian.Berghoff@mayflower.de
  82. 82. LINKS , Slideshare folgtSlides in Markdown RxJS docs Marbles Liste an Tutorials Repository Ausführliches Tutorial Video Tutorials Buch ALTERNATIVEN cyclejs BACONJS
  83. 83. THANK YOU!
  84. 84. < <

×