Functional Reactive JavaScript

Functional Reactive JavaScript

Slides from a talk at the SF JavaScript meetup: http://www.meetup.com/jsmeetup/events/199214912/

code examples from the talk: http://frp-talk-examples.thepete.net/

Fe6b81005d1553accd6b2a28f6a2bef1?s=128

Pete Hodgson

August 26, 2014
Tweet

Transcript

  1. Functional 
 Reactive
 JavaScript

  2. Functional 
 Reactive
 Programming

  3. variable
 snapshot of a value 
 at a specific time

    stream
 all future values over time
  4. Functional 
 Reactive
 Programming

  5. UI elements produce streams of values. Functions combine and transform

    those streams into new streams. Streams can be assigned to UI attributes 
 to effect UI output.
  6. our approach 
 for this evening

  7. –Johnny Appleseed “Type a quote here.”

  8. for bonus points: TDD*! * Test-Driven Development

  9. me me me Pete Hodgson Consultant at ThoughtWorks @ph1 blog.thepete.net

  10. example #1. slider & label

  11. slider <div> var wireUpSliderToLabel = function ( $slider, $label ){

    var sliderValue = $slider.asEventStream('input', eventToVal); sliderValue.assign( $label, "text" ); }; ! var eventToVal = function(e){ return $(e.target).val(); };
  12. slider <div> var wireUpSliderToLabel = function ( $slider, $label ){

    var sliderValue = $slider.asEventStream('input', eventToVal); sliderValue.assign( $label, "text" ); }; ! var eventToVal = function(e){ return $(e.target).val(); };
  13. slider <div> var wireUpSliderToLabel = function ( $slider, $label ){

    var sliderValue = $slider.asEventStream('input', eventToVal); sliderValue.assign( $label, "text" ); }; ! var eventToVal = function(e){ return $(e.target).val(); };
  14. slider <div> 5 5 var wireUpSliderToLabel = function ( $slider,

    $label ){ var sliderValue = $slider.asEventStream('input', eventToVal); sliderValue.assign( $label, "text" ); }; ! var eventToVal = function(e){ return $(e.target).val(); };
  15. slider <div> 5 5 5 var wireUpSliderToLabel = function (

    $slider, $label ){ var sliderValue = $slider.asEventStream('input', eventToVal); sliderValue.assign( $label, "text" ); }; ! var eventToVal = function(e){ return $(e.target).val(); };
  16. 5 5 5 2 var wireUpSliderToLabel = function ( $slider,

    $label ){ var sliderValue = $slider.asEventStream('input', eventToVal); sliderValue.assign( $label, "text" ); }; ! var eventToVal = function(e){ return $(e.target).val(); };
  17. 5 5 5 2 2 var wireUpSliderToLabel = function (

    $slider, $label ){ var sliderValue = $slider.asEventStream('input', eventToVal); sliderValue.assign( $label, "text" ); }; ! var eventToVal = function(e){ return $(e.target).val(); };
  18. epiphany declarative, not imperative

  19. example #2. slider & label w. formatting

  20. formatFn var wireUpSliderToFormattedLabel = function ( $slider, $label ){ var

    sliderValue = $slider.asEventStream('input', eventToVal); var formattedValue = sliderValue.map( ratioToPercentage ); formattedValue.assign( $label, "text" ); }; ! var ratioToPercentage = function(ratio){ return "" + Math.round(ratio*100) + "%"; } ! var eventToVal = function(e){ return $(e.target).val(); };
  21. formatFn 0.05 var wireUpSliderToFormattedLabel = function ( $slider, $label ){

    var sliderValue = $slider.asEventStream('input', eventToVal); var formattedValue = sliderValue.map( ratioToPercentage ); formattedValue.assign( $label, "text" ); }; ! var ratioToPercentage = function(ratio){ return "" + Math.round(ratio*100) + "%"; } ! var eventToVal = function(e){ return $(e.target).val(); };
  22. “5%” formatFn 0.05 0.05 var wireUpSliderToFormattedLabel = function ( $slider,

    $label ){ var sliderValue = $slider.asEventStream('input', eventToVal); var formattedValue = sliderValue.map( ratioToPercentage ); formattedValue.assign( $label, "text" ); }; ! var ratioToPercentage = function(ratio){ return "" + Math.round(ratio*100) + "%"; } ! var eventToVal = function(e){ return $(e.target).val(); };
  23. “5%” 5% formatFn 0.05 0.05 var wireUpSliderToFormattedLabel = function (

    $slider, $label ){ var sliderValue = $slider.asEventStream('input', eventToVal); var formattedValue = sliderValue.map( ratioToPercentage ); formattedValue.assign( $label, "text" ); }; ! var ratioToPercentage = function(ratio){ return "" + Math.round(ratio*100) + "%"; } ! var eventToVal = function(e){ return $(e.target).val(); };
  24. epiphany compose-ability (pipes & filters)

  25. example #3. slider & grayscale swatch

  26. example #4. sliders & color swatch

  27. combineFn

  28. combineFn 0.7 0.1 0.5

  29. combineFn 0.7 0.1 0.5 { r: 0.7, g: 0.1, b:

    0.5 }
  30. combineFn 0.7 0.5 0.9 { r: 0.7, g: 0.1, b:

    0.5 }
  31. combineFn 0.7 0.5 0.9 { r: 0.7, g: 0.9, b:

    0.5 }
  32. epiphany most recent value is always available

  33. epiphany very little need to manage mutable state

  34. back to 
 theory

  35. variable
 snapshot of a value 
 at a specific time

    stream
 all future values over time
  36. var a = 12 var b = a + 10

    // b == 22 a = 20 // b == 22
  37. var a = 12 var b = a + 10

    // b == 22 a = 20 // b == 22 var a = aStreamWith(12) var b = a.map( -> + 10 ) a.updateTo(20)
  38. we’re just getting started

  39. frp-talk-examples.thepete.net

  40. thanks! questions?

  41. @ph1 phodgson@thoughtworks.com frp-talk-examples.thepete.net blog.thepete.net slides.thepete.net