Upgrade to Pro — share decks privately, control downloads, hide ads and more …

From Imperative To Reactive Thinking

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

From Imperative To Reactive Thinking

Avatar for Todd Motto

Todd Motto

July 10, 2017

More Decks by Todd Motto

Other Decks in Programming

Transcript

  1. DISCOVERING PATTERNS Ob se rve r Pa tte rn Se

    que nce s a nd O pe ra tors
  2. PATTERNS DISCOVERED Ob se rve r Pa tte rn Se

    que nce s a nd O pe ra tors
  3. Elements of our game 1. <div id="james">James</div> 2. <div id="todd">Todd</div>

    3. <div id="ball"></div> 4. 5. <button id="start">Start</button>
  4. Game Helpers 6. const CHANCE_OF_BAD_THROW = 0.5; 7. 8. //

    Throw affects chances of catching 9. function checkDropped(isBadThrow): boolean; 1. // Helpers to move ball around in the game 2. function addBall(player: Element): void; 3. function removeBall(player: Element): void; 4. 5. // Simple 50/50 chance of bad throw We use the throw quality to determine whether the ball is caught or not.
  5. TODO 1. S ta rt the ga me on `

    sta rtB tn` click 2. Th row a nd ca tch the ball be twee n 2 pla ye rs 3. Check each th row to see if i t wa s “bad” 4. Check ca tch, e ndi ng the ga me on d rop
  6. Starting the game 1. function handleClick() { 2. // our

    game code 3. } 4. 5. startBtn.addEventListener('click', handleClick);
  7. TODO 1. S ta rt the ga me on `

    sta rtB tn` click 2. Th row a nd ca tch the ball be twee n 2 pla ye rs 3. Check each th row to see if i t wa s “bad” 4. Check ca tch, e ndi ng the ga me on d rop
  8. 5. // TODO 6. // - person1 starts with ball

    7. // - wait while they get ready to throw 1. // Our two refs to the people DOM nodes 2. throwAndCatchBetween(james, todd); 3. 4. function throwAndCatchBetween(person1, person2) {
  9. Core throwing and catching 2. // person1 starts with ball

    1. function throwAndCatchBetween(person1, person2) {
  10. ...now for humans 1. function throwAndCatchBetween(person1, person2) { 2. //

    person1 starts with ball 3. addBall(person1); 4. 5. // wait while they get ready to throw 6. setTimeout(() => { 7. 8. // person1 throws ball 9. removeBall(person1); 10. 11. // ball travels through the air 12. setTimeout(() => { 13. 14. // person2 catches ball 15. addBall(person2); 16. 17. // Back again! 18. throwAndCatchBetween(person2, person1); 19. Ball flies throught the air for 1 second before being caught.
  11. TODO 1. S ta rt the ga me on `

    sta rtB tn` click 2. Th row a nd ca tch the ball be twee n 2 pla ye rs 3. Check each th row to see if i t wa s “bad” 4. Check ca tch, e ndi ng the ga me on d rop
  12. Check throw quality 8. // person1 throws ball 9. removeBall(person1);

    10. // capture if throw was bad 11. const isBadThrow = 12. Math.random() <= CHANCE_OF_BAD_THROW; 1. function throwAndCatchBetween(person1, person2) { 2. // person1 starts with ball 3. addBall(person1); 4. 5. // wait while they get ready to throw 6. setTimeout(() => { 7. 13. 14. // ball travels through the air 15. setTimeout(() => { 16. 17. // person2 catches ball 18. addBall(person2); 19. 20. // Back again! 21. throwAndCatchBetween(person2, person1);
  13. TODO 1. S ta rt the ga me on `

    sta rtB tn` click 2. Th row a nd ca tch the ball be twee n 2 pla ye rs 3. Check each th row to see if i t wa s “bad” 4. Check ca tch, e ndi ng the ga me on d rop
  14. Check if ball was dropped 10. // capture if throw

    was bad 11. const isBadThrow = 12. Math.random() <= CHANCE_OF_BAD_THROW; 13. 14. // ball travels through the air 15. setTimeout(() => { 16. 17. if (checkDropped(isBadThrow)) { 18. return // Game over: Ball dropped 19. } 3. addBall(person1); 4. 5. // wait while they get ready to throw 6. setTimeout(() => { 7. 8. // person1 throws ball 9. removeBall(person1); 20. 21. // person2 catches ball 22. addBall(person2); 23. 24. // Back again! 25. throwAndCatchBetween(person2, person1); 26.
  15. 1. S ta rt the ga me on ` sta

    rtB tn` click 2. Th row a nd ca tch the ball be twee n 2 pla ye rs 3. Check each th row to see if i t wa s “bad” 4. Check ca tch, e ndi ng the ga me on d rop
  16. TODO 1. Ob se rvable<S ta rt b utton click

    s> 2. Ob se rvable<Th rowi ng the ball> 3. Ob se rvable<Ca tchi ng ( or not!) the ball>
  17. Observable<Start button clicks> 6. // Start listening for clicks 7.

    game$.subscribe(); 1. const startClick$ = Rx.Observable 2. .fromEvent(startBtn, 'click'); 3. 4. const game$ = startClick$; 5. We subscribe to the Observable to begin actually listening for the start button click events.
  18. Turn a click into throw and catch! 4. const game$

    = startClick$ 5. .switchMap( 6. handleThrowAndCatchBetween(james, todd) 7. ); 1. const startClick$ = Rx.Observable 2. .fromEvent(startBtn, 'click'); 3. 8. 9. // Start listening for clicks 10. game$.subscribe();
  19. Core throwing and catching 1. // Usage 2. .switchMap( 3.

    handleThrowAndCatchBetween(james, todd) 4. ); 5.
  20. TODO 1. Ob se rvable<S ta rt b utton click

    s> 2. Ob se rvable<Pe rson th rowi ng the ball> 3. Ob se rvable<Pe rson ca tchi ng the ball>
  21. What events make up a "throw"? 1. // person1 starts

    with ball 2. addBall(person1); 3. 4. // wait while they get ready to throw 5. setTimeout(() => { 6. 7. // person1 throws ball 8. // capture if throw was bad 9. removeBall(person1); 10. const isBadThrow = 11. Math.random() <= CHANCE_OF_BAD_THROW; 12. We can extract the relevant concepts from our imperative example...
  22. Observable<Person throwing the ball> 1. // capture if throw was

    bad 2. const isBadThrow = 3. Math.random() <= CHANCE_OF_BAD_THROW; 4. 5. const throw$ = Rx.Observable.of(isBadThrow); We can make our initial throw$ stream encapsulate the throw quality (so we can evaluate it later).
  23. Observable<Person throwing the ball> 9. // ball travels through the

    air 10. .delay(1000); 1. // capture if throw was bad 2. const throw$ = Rx.Observable.of(isBadThrow) 3. // person1 starts with ball 4. .do(() => addBall(person1)) 5. // wait while they get ready to throw 6. .delay(1000) 7. // person1 throws ball 8. .do(() => removeBall(person1))
  24. Observable<Person throwing the ball> 4. return Rx.Observable.of(isBadThrow) 5. .do(() =>

    addBall(person)) 6. .delay(1000) 7. .do(() => removeBall(person)) 8. .delay(1000); 9. } 1. function handleThrow$From(person) { 2. const isBadThrow = 3. Math.random() <= CHANCE_OF_BAD_THROW;
  25. "Plug in" the throwing for p1 and p2 1. //

    Usage 2. .switchMap( 3. handleThrowAndCatchBetween(james, todd) 4. ); 5.
  26. TODO 1. Ob se rvable<S ta rt b utton click

    s> 2. Ob se rvable<Pe rson th rowi ng the ball> 3. Ob se rvable<Pe rson ca tchi ng the ball>
  27. What events make up a "catch"? 5. // Ball is

    caught succesfully 6. return Rx.Observable.of('') 7. .do(() => addBall(person)) 1. // Ball is dropped 2. if (checkDropped(isBadThrow)) { 3. return Rx.Observable.throw(`Ball dropped`) 4. } If the ball is caught, we return an Observable (the value isn't important) and add the ball to the person as normal.
  28. Observable<Person catching the ball> 2. // The returned function will

    be used within 1. function handleCatch$By(person) { The `isBadThrow` value will be passed in via the switchMap from the previous throw$
  29. "Plug in" the throwing for p1 and p2 1. //

    Usage 2. .switchMap( 3. handleThrowAndCatchBetween(james, todd) 4. ); 5.
  30. 1. Ob se rvable<S ta rt b utton click s>

    2. Ob se rvable<Pe rson th rowi ng the ball> 3. Ob se rvable<Pe rson ca tchi ng the ball>