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 programming with RxJS - ByteConf 2018

736 Aufrufe

Veröffentlicht am

Reactive programming paradigms are all around us. So why does is it awesome? We'll explore reactive programming in standards, frameworks and libraries and talk about how to think reactively.

Then we'll take a more practical approach and talk about how to utilize reactive programming patterns with an abstraction like RxJS, a domain specific language for reacting to events and how using this abstraction can make your development life much easier in React Native.

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

Reactive programming with RxJS - ByteConf 2018

  1. 1. ● ● ● ● ● ● ● ●
  2. 2. ● ● ● ●
  3. 3. ● ● ●
  4. 4. ● ● ● ● ● ● ● ● ● ●
  5. 5. fetch('fruitsnacks.json') .then(resp => resp.json()) .then(fruitsnacks => console.log('I have fruit snacks!'));
  6. 6. ● ● ● ● ● ● ● ● ●
  7. 7. import { ajax } from ‘rxjs/ajax’; ajax.getJSON(‘fruitsnacks.json’) .subscribe(fruitsnacks => console.log(fruitsnacks));
  8. 8. ● ● ●
  9. 9. button.on('click’);
  10. 10. var numbers = [15, 8, 42, 4, 32]; function update() { var selection = d3.select(“#chart”) .selectAll(“.bar”).data(numbers) .style(“height”, function(d) { return d + “px”; }) .style(“margin-top”, function(d) { return (100 - d) + “px”; }); selection.enter() .append(“div”).attr(“class”, “bar”) .style(“height”, function(d) { return (100 - d) + “px”; }) .on(“click”, function(e, i) { numbers.splice(i, 1); update(); }); selection.exit().remove(); }; update();
  11. 11. ● ● ● ● ●
  12. 12. Reactive
  13. 13. set of values over time
  14. 14. set of values over time
  15. 15. set of values over time
  16. 16. set of values over time
  17. 17. function myObservable() { }
  18. 18. function myObservable(observer) { }
  19. 19. function myObservable(observer) { observer.next(1); }
  20. 20. function myObservable(observer) { observer.next(1); if (someCondition) { observer.error(new Error('end of the world')); } }
  21. 21. function myObservable(observer) { observer.next(1); if (someCondition) { observer.error(new Error('end of the world')); } observer.complete(); }
  22. 22. const observer = { next(value) { console.log(value); }, error(err) { console.error(err); }, complete() { console.log('done'); }, }; myObservable(observer);
  23. 23. const teardown = myObservable({ next(value) { console.log(value); }, error(err) { console.error(err); }, complete() { console.log('done'); }, }); teardown();
  24. 24. function myObservable(observer) { observer.next(1); if (someCondition) { observer.error(new Error('end of the world')); } observer.complete(); observer.next('oops'); }
  25. 25. const teardown = myObservable({ next(value) { console.log(value); }, error(err) { console.error(err); }, complete() { console.log('done'); }, }); if (teardown) teardown();
  26. 26. myObservable({ next(value) { console.log(value); }, error(err) { console.error(err); }, }); complete? where are you?!
  27. 27. const teardown = myObservable({ next(value) { console.log(value); }, error(err) { console.error(err); if (teardown) teardown(); }, complete() { console.log('done'); if (teardown) teardown(); }, }); if (teardown) teardown();
  28. 28. function myObservable(observer) { observer.next(1); if (someCondition) { observer.error(new Error('end of the world')); } observer.complete(); }
  29. 29. const myObservable = new Observable((observer) => { observer.next(1); if (someCondition) { observer.error(new Error('end of the world')); } observer.complete(); });
  30. 30. const teardown = myObservable({ next(value) { console.log(value); }, error(err) { console.error(err); if (teardown) teardown(); }, complete() { console.log('done'); if (teardown) teardown(); }, }); if (teardown) teardown();
  31. 31. const subscription = myObservable.subscribe({ next(value) { console.log(value); }, error(err) { console.error(err); }, complete() { console.log('done'); }, }); subscription.unsubscribe();
  32. 32. const subscription = myObservable.subscribe({ next(value) { console.log(value); }, error(err) { console.error(err); }, complete() { console.log('done'); }, }); subscription.unsubscribe();
  33. 33. const arr = [1, 2, 3, 4, 5, 6, 7]; arr.filter(x => x % 2 === 0); // [2, 4, 6] arr.map(x => x + x); // [2, 4, 6, 8, 10, 12, 14] arr.filter(x => x % 2 === 0) .map(x => x + x); // [4, 8, 12]
  34. 34. import { of as observableOf } from 'rxjs'; import { map, filter } from 'rxjs/operators'; const src = observableOf(1, 2, 3, 4, 5, 6, 7); src.pipe( filter(x => x % 2 === 0), map(x => x + x), ).subscribe(x => console.log(x)); // 4...8...12...
  35. 35. import { Observable } from 'rxjs'; export function map(fn) { return (source) => new Observable(observer => { return source.subscribe({ next(value) { observer.next(fn(value)); }, error(err) { observer.error(err); }, complete() { observer.complete(); }, }); }); }
  36. 36. import { Observable } from 'rxjs'; export function map(fn) { return (source) => new Observable(observer => { return source.subscribe({ next(value) { observer.next(fn(value)); }, error(err) { observer.error(err); }, complete() { observer.complete(); }, }); }); }
  37. 37. import { Observable } from 'rxjs'; export function map(fn) { return (source) => new Observable(observer => { return source.subscribe({ next(value) { observer.next(fn(value)); }, error(err) { observer.error(err); }, complete() { observer.complete(); }, }); }); }
  38. 38. import { Observable } from 'rxjs'; export function map(fn) { return (source) => new Observable(observer => { return source.subscribe({ next(value) { observer.next(fn(value)); }, error(err) { observer.error(err); }, complete() { observer.complete(); }, }); }); }
  39. 39. import { Observable } from 'rxjs'; export function map(fn) { return (source) => new Observable(observer => { return source.subscribe({ next(value) { observer.next(fn(value)); }, error(err) { observer.error(err); }, complete() { observer.complete(); }, }); }); }
  40. 40. ● ● ● ● ● ● ● ● ● ●
  41. 41. import React from ‘react’; import { StyleSheet, Text, View, Image } from ‘react-native’; import { Subject, Subscription } from ‘rxjs’; import { exhaustMap, takeUntil, map, filter } from ‘rxjs/operators’; import donut from ‘./donut.png’;
  42. 42. export default class App extends React.Component { touchStart = new Subject(); touchMove = new Subject(); touchEnd = new Subject(); subscription = new Subscription(); state = { locationX: -100, locationY: -200, pageX: 0, pageY: 0 };
  43. 43. componentDidMount() { this.subscription.add(this.touchStart.pipe( exhaustMap(start => { const touchId = start.id; const locationX = start.nativeEvent.locationX; const locationY = start.nativeEvent.locationY; return this.touchMove.pipe( filter(move => move.id === touchId), map(move => ({ pageX: move.nativeEvent.pageX, pageY: move.nativeEvent.pageY, locationX, locationY,
  44. 44. const locationX = start.nativeEvent.locationX; const locationY = start.nativeEvent.locationY; return this.touchMove.pipe( filter(move => move.id === touchId), map(move => ({ pageX: move.nativeEvent.pageX, pageY: move.nativeEvent.pageY, locationX, locationY, })), takeUntil(this.touchEnd), ) }) ).subscribe((state) => { this.setState(state); }))
  45. 45. const locationY = start.nativeEvent.locationY; return this.touchMove.pipe( filter(move => move.id === touchId), map(move => ({ pageX: move.nativeEvent.pageX, pageY: move.nativeEvent.pageY, locationX, locationY, })), takeUntil(this.touchEnd), ) }) ).subscribe((state) => { this.setState(state); })) }
  46. 46. render() { let donutX = 0; let donutY = 0; const { pageX, pageY, locationX, locationY } = this.state; donutX = pageX - locationX; donutY = pageY - locationY; return ( <View> <Image onMoveShouldSetResponder={() => true } onMoveShouldSetResponderCapture={() => true } onResponderGrant={(e) => this.touchStart.next(e) } onResponderMove={(e) => this.touchMove.next(e) } onResponderRelease={(e) => this.touchEnd.next(e) } source={donut}>
  47. 47. let donutY = 0; const { pageX, pageY, locationX, locationY } = this.state; donutX = pageX - locationX; donutY = pageY - locationY; return ( <View> <Image onMoveShouldSetResponder={() => true } onMoveShouldSetResponderCapture={() => true } onResponderGrant={(e) => this.touchStart.next(e) } onResponderMove={(e) => this.touchMove.next(e) } onResponderRelease={(e) => this.touchEnd.next(e) } source={donut}> </Image> </View> );
  48. 48. import React from ‘react’; import { StyleSheet, Text, View, Image, Button } from ‘react-native’; import { webSocket } from ‘rxjs/webSocket’; import { groupBy, mergeMap, takeUntil, finalize } from ‘rxjs/operators’; import { timer } from ‘rxjs’; import kenwheeler from ‘./ken_wheeler.png’;
  49. 49. export default class App extends React.Component { state = { randomKens: {} }; socket$ = webSocket(‘ws://localhost:8080’); requestKenHead() { const msg = JSON.stringify({ type: ‘REQUEST_KEN_HEAD’ }); this.socket$.next(msg); }
  50. 50. componentDidMount() { const kenHead$ = this.socket$.pipe { groupBy(data => data.id), mergeMap(singleKenStream => singleKenStream.pipe( takeUntil( timer(3000), ), finalize(() => { const dataId = singleKenStream.key; const randomKens = { ...this.state.randomKens }; delete randomKens[dataId]; this.setState({ randomKens }); }) )
  51. 51. const kenHead$ = this.socket$.pipe { groupBy(data => data.id), mergeMap(singleKenStream => singleKenStream.pipe( takeUntil( timer(3000), ), finalize(() => { const dataId = singleKenStream.key; const randomKens = { ...this.state.randomKens }; delete randomKens[dataId]; this.setState({ randomKens }); }) ) ) );
  52. 52. this.subscription = kenHead$.subscribe(data => { this.setState({ randomKens: { ...this.state.randomKens, [data.id]: { id: data.id, x: data.x, y: data.y } } }); }); componentWillUnmount() { this.subscription.unsubscribe(); }
  53. 53. render() { return ( <View> {Object.values(this.state.randomKens).map(randomKen => <Image key={randomKen.id} source={kenwheeler} style={{ position: ‘absolute’, left: randomKen.x, top: randomKen.y, }} /> )} <Button onPress={() => this.requestKenHead()} title=”add a ken bobble” /> </View> );

×