Async Code In A Nutshell

A fairly succinct journey through the many ways javascript developers have learned to cope with asynchrony. Callbacks vs Promises vs RxJS vs async/await link

// The problem const getUser = () => { setTimeout(() => { return {name: 'Max'} }, 2000); }; const user = getUser(); // user is null console.log(user.name); // so this won't work

// The callback const getUser = (cb) => { setTimeout(() => { cb({name: 'Max'}); }, 2000); }; getUser((user) => { console.log(user.name); // Prints 'Max' after 2 seconds })

// callback hell const checkAuth = (cb) => { // timer simulates network latency setTimeout(() => { cb({isAuth: true}); }, 2000); }; const getUser = (authInfo, cb) => { if (!authInfo.isAuth) { cb(null); return; } setTimeout(() => { cb({name: 'Max'}); }, 2000); }; // this next part get much worse in Real Life checkAuth((authInfo) => { getUser(authInfo, (user) => { console.log(user.name); }); });

// The promise const getUser = () => { return new Promise(resolve => { setTimeout(() => { resolve({name: 'Max'}); }, 2000); }); }; getUser() .then(user => { console.log(user.name); })

// Promised relief from callback hell checkAuth() .then(authStatus => getUser(authStatus)) .then(user => console.log(user.name)) .catch(error => { // handle error here });

// Promises only resolve once const button = document.querySelector('button'); const handleClick = () => { return new Promise(resolve => { button.addEventListener('click', () => { resolve(event); }); }); }; // So this doesn't do what you mean handleClick().then(event => { console.log(event.target); });

_N.B. the RxJS examples are apparently out-of-date_

// RxJS Observables handle event streams const button = document.querySelector('button'); const observable = Rx.Observable.fromEvent(button, 'click'); observable.subscribe( event => console.log(event.target), error => console.log(error) );

// RxJS switchMap operator to chain observables const button = document.querySelector('button'); Rx.Observable.fromEvent(button, 'click') .switchMap(event => Rx.Observable.timer(1000)) .subscribe( (data) => console.log(data) );

// RxJS offers a menagerie of stream operators // maybe even convenient enough for non-async code const observable = Rx.Observable.of({name: 'Max'}); observable .pluck('name') .subscribe(console.log);

// async/await also promising ;-) async function fetchUser() { try { const auth = await checkAuth(); const user = await getUser(auth); return user; } catch (error) { return {name: 'Default'}; } } fetchUser().then(user => console.log(user.name));

.

// more modern RxJS example -- pipe! const { fromEvent } = rxjs; const { throttleTime, scan } = rxjs.operators; const button = document.querySelector('button'); fromEvent(button, 'click').pipe( throttleTime(5000), scan(count => count + 1, 0) ) .subscribe(count => console.log(`Clicked ${count} times`));

Apparently generalizing over that progression of asynchrony: Why we need callbags link

Mostly tangential comment caught my eye _(emphasis added)_: > the long-term goal of Cycle.js : to be a **framework for visual programming**

André Staltz also cryptographicly signs his articles: > You can make sure that the author wrote this post by copy-pasting this signature into this Keybase page .

Once upon a time, I observed event-based computing in GUIs was showing up server-side: blog . I also claimed there that pipeline pattern and state pattern were duals. Do I finally live in a world where these reactive event streams flow from business analysis through the network all the way through the UI? Event Storming