Rethink Async With RXJS

Download Rethink Async With RXJS

Post on 17-Dec-2014

1.348 views

Category:

Technology

6 download

Embed Size (px)

DESCRIPTION

This is an updated version of my "Add more fun to your functional programming with RXJS". It includes a bit more background information on Reactive programming.

TRANSCRIPT

<ul><li> 1. Rethink Async with RXJS </li> <li> 2. Senior UI Engineer at About Me bittersweetryan ranklam@netix.com </li> <li> 3. Before We Begin </li> <li> 4. Before We Begin Be KIND to those of us with OCD and </li> <li> 5. Before We Begin Change those Dropbox icons to B&amp;W! </li> <li> 6. Reactive Programming! </li> <li> 7. Reactive Programming Java Groovy and JavaScript At Netix do a lot of RX .NET </li> <li> 8. We Build This With RXJS </li> <li> 9. Reactive Programming What if? The iterator pattern and observer met at a bar, ! fell in love, got married, and had a baby? </li> <li> 10. Reactive Programming </li> <li> 11. Reactive Programming What if? This baby would allow you to use the same code to ! respond to events and asynchronous operations? </li> <li> 12. Meet Observable </li> <li> 13. Observables What to events and async functions have in common? </li> <li> 14. Observables As a mouse moves, doesnt it just emit coordinates? Tracking Mouse Movements </li> <li> 15. Observables Tracking Mouse Movements 1s 2s Mousedown 0s Mouseup {x : 200, y: 521} {x : 240, y: 552} {x : 210, y: 602} {x : 199, y: 579} {x : 221, y: 530} {x : 218, y: 570} {x : 200, y: 599} </li> <li> 16. Observables var mouseMoves = Observable.fromEvent( mouseDown ) .takeUntil( mouseUp ) .map( function( mouseEvent ){ return { x : mouseEvent.clientX, y : mouseEvent.clientY }; } ) ; ! mouseMoves.subscribe( function( cords ){ //do stuff for each mouse move cord }); Mouse Moves Observable </li> <li> 17. Observables Observables Everywhere! Events! AJAX Requests! Node Functions! Arrays! Promises! And more. </li> <li> 18. Observables Why not another Async approach? Replayable! Composable! Cancellable! Cache-able! Shareable! Can emit multiple value-able </li> <li> 19. Functional Review! (With an RX twist) </li> <li> 20. Functional Review Map Reduce Filter Zip </li> <li> 21. var searchResultsSets = keyups. map( function( key ){ return Observable.getJSON('/search?' + input.value) }); Functional Review Map - Transforms data </li> <li> 22. var searchResultsSets = keyups. filter( function ( key ){ return input.value.length &gt; 1; }). map( function( key ){ return Observable.getJSON('/search?' + input.value) ); Functional Review Filter - Narrows Collections </li> <li> 23. var html = searchResultsSets. reduce(function( prev,curr ) { return prev + '</li><li>' + curr.name + ''; },'' ); Functional Review Reduce - Turns a collection into a single value Initial prev value. </li><li> 24. Functional Review Zip - Combines two collections var movies = [ 'Super Troopers', 'Pulp Fiction', 'Fargo' ] ; var boxArts =[ '/cdn/23212/120x80', '/cdn/73212/120x80','/cdn/99212/120x80' ] ; ! var withArt = Observable. zip(movies, boxarts, function(movie, boxart){ return {title : movie, boxart : boxart}; }); ! //[{title : 'Super Troo', boxart : '/cdn'}, // {title : 'Pulp Fict', boxart : '/cdn' }, // {title : 'Fargo', boxart : 'cdn' } ] </li> <li> 25. Functional Review Observable Data Streams Are Like Crazy Straws keyPresses Observable subscribe throttle lter map distinctUntilChanged reduce </li> <li> 26. Thinking Functionally </li> <li> 27. Thinking Functionally Replace loops with map. searchResults = Observable. getJSON(/people? + input.value); ! searchResults. forEach( function( reps ){ var names = []; for( var i = 1; i &lt; resp; i++ ){ var name = data[i].fName + ' ' + data[i].lName; names.push( name ); } }); </li> <li> 28. Thinking Functionally Replace loops with map and reduce. searchResults = Observable. getJSON(/people? + input.value). map( function( data ){ return data.fName + data.lName; } ); ! searchResults.forEach( function( resp ){ //resp will now be the names array }) </li> <li> 29. Thinking Functionally Replace ifs with lters. var keyPresses = O.fromEvent( el, 'keyup' ) ! keyPresses.forEach( function( e ){ if( e.which === keys.enter ){ //=&gt; no! //do something } }); </li> <li> 30. Thinking Functionally Replace ifs with lters. var enterPresses = O.fromEvent( el, 'keyup' ) .filter( function( e ){ return e.which &amp;&amp; e.which === keys.enter; }); ! enterPresses.forEach( function( e ){ //do something }); </li> <li> 31. Thinking Functionally Dont put too much in a single stream. var submits = O.fromEvent(input,'keypresses'). throttle(). map( function( e ){ return e.which } ). filter( function( key ){ return key === keys.enter || keys.escape; }). map(). reduce(). ... Smaller streams are OK. </li> <li> 32. Thinking Functionally var keys = Observable.fromEvent(input,'keypresses'). throttle(). map( function( e ){ return e.which } ); ! var enters = keys.filter( function( key ) ){ return e.which === keys.enter; } ! var escapes = keys.filter( function( key ) ){ Dont put too much in a single stream. Smaller streams are OK. </li> <li> 33. Flattening Patterns! managing concurrency! </li> <li> 34. Observables = Events Over Time Key presses over time .5s 1s 1.5s 2s 2.5s 3s B R E A K IJ 1; }). map( function( e ){ return Observable. getJSON('/search?' + input.value); }). switchLatest(); Animated Autocomplete </li> <li> 46. var animateOuts = keyups. map(function( resultSet ){ return animateOut(resultsDiv); }); ! var animateIns = searchResultsSets. map( function( resultSet ){ return Observable. of(resultsSet). concat(animateIn(resultsDiv)); }); Animated Autocomplete </li> <li> 47. var resultSets = animateOuts. merge(animateIns). concatAll(); ! resultSets. forEach( function( resultSet ){ if (resultSet.length === 0) { $('.search-results').addClass('hidden'); } else { resultsDiv.innerHTML = toHTML(resultSet ); } } ); Animated Autocomplete </li> <li> 48. var keyups = Observable. fromEvent( searchInput, keypress'); !var searchResultsSets = keyups. filter( function ( e ){ return input.value.length &gt; 1; }). map( function( e ){ return Observable. getJSON('/search?' + input.value); }). switchLatest(); var animateOuts = keyups. map(function( resultSet ){ return animateOut(resultsDiv); }); !var animateIns = searchResultsSets. map( function( resultSet ){ return Observable. of(resultsSet). concat(animateIn(resultsDiv)); }); !var resultSets = animateOuts. merge(animateIns). concatAll(); !resultSets. forEach( function( resultSet ){ if (resultSet.length === 0) { $('.search-results').addClass('hidden'); } else { resultsDiv.innerHTML = toHTML(resultSet ); } } ); Animated Autocomplete </li> <li> 49. In Conclusion! ! ranklam@netix.com @bittersweetryan! </li> <li> 50. In Conclusion Observables are a POWERFUL abstraction! Requires a bit of mental rewiring! The RX API is HUGE, take baby steps! Merging strategies are the key coordinating async! Compose streams of data from small streams </li> <li> 51. To Find Out More http://github.com/jhusain/learnrx! https://github.com/Reactive-Extensions/RxJS/tree/master/doc! Chat with me </li> <li> 52. Questions?! </li> <li> 53. Thank You.! ! ranklam@netix.com @bittersweetryan! </li> </ul>