March 2017, Denko Mancheski
workshop #3
- What is async and how does it work
- JS async callback hell
- Promises
- RxJS
THINKING ASYNCHRONOUSLY IS HARD...
BUT CHEER UP, EVENTUALLY YOU'LL GET IT!
EVENTUALLY YOU'LL GET IT...
WHAT IS ASYNC?
CODE THAT DOESN'T WAIT!
Will execute later
YOUR BRAIN IS AN ASYNCHRONOUS MACHINE
#devnexus #asyncprogramming #omgenius
OK, GOT IT
IS THERE ANYTHING MORE?
Pseudo-code
JS is an event loop
JS is single-threaded
Async callbacks run on a basically empty call stack
Which makes debugging… interesting.
Chrome got async call stacks around version 35 (mid-2014).
“Traverses” async handovers: timers, XHR, promises, rAF, most observers, postMessage, FileSystem, IndexedDB…
Check out: http://latentflip.com/loupe/
Triangle of doom
Mind / Code mapping is terrible.
(mostly because no returned value / entity)
Error management is a friggin’ mess.
Will it even run?
Will it run either error or success callbacks, not both?
Will it run only once?
Trustworthy: only one callback, only once, guaranteed. Plus, exceptions!
Composable: chainable, with injection and casting.
New abstractions
Slight performance penalty (improves, esp. with natives)
Code flow remains non-intuitive / very different from sync code.
Been there a long time, under various forms and names.
Came into JS in 2007 through Dōjō.
Promises/A proposed in CommonJS in 2009 (Kris Zyp)
Promises/A+ in 2012 (Brian Cavalier, Domenic Denicola et at.)
Lack of Cancelation
Synhronization
Exceptions
...
RxJS
EVERYTHING IS A STREAM
(click events, user inputs, data from server)
Observable creation
Observable usage
function searchWikipedia(term) {
return $.ajaxAsObservable( /* … */ )
.select(function(results) { return results.data; }); // Grab the data property
}
var input = $('#textInput');
var keyup = input.keyupAsObservable() // Event stream!
.select(function() { return input.val(); }) // Grab the field value
.where(function(text) { return text.length > 2; }) // Only proceed when long enough
.throttle(500); // Slow down, breathe…
var searcher = keyup
.select(function(text) { return searchWikipedia(text); }) // Map on an XHR *result*!
.switchLatest() // Only keep latest response
.where(function(data) { return data.length === 2; }); // Only keep useful results
searcher.subscribe(renderResults); // React to final stream by rendering UI
Avoid mutable state & side effects
Recursion
Higher-order functions
Function composition
Lazy evaluation
Pattern matching
Examples: map, filter, reduce, some..
We call these - Operators
RxJS =
Observables + Operators
Observable could be:
A push based collection
Operators could be:
Why RxJS
COLD is when your observable creates the producer
HOT is when your observable closes over the producer
const source = new Observable((observer) => {
const socket = new WebSocket('ws://someurl');
socket.addEventListener('message', (e) => observer.next(e));
return () => socket.close();
});
const socket = new WebSocket('ws://someurl');
const source = new Observable((observer) => {
socket.addEventListener('message', (e) => observer.next(e));
});
RxJS Subjects
Subject
both an observer and an observable. You can use a subject to subscribe all the observers, and then subscribe the subject to a backend data source
ReplaySubject
stores all the values that it has published. Therefore, when you subscribe to it, you automatically receive an entire history of values that it has published,
BehaviorSubject
is similar to ReplaySubject, except that it only stored the last value it published. BehaviourSubject also requires a default value upon initialization.
AsyncSubject
is similar to the Replay and Behavior subjects, however it will only store the last value, and only publish it when the sequence is completed
Useful Resources
If you have any question, do not hesitate:
denkomanceski@gmail.com