dead-simple async control flow with coroutines
TRANSCRIPT
![Page 1: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/1.jpg)
Dead-Simple Async
Control Flow with
Coroutines
by Travis Kaufman (@traviskaufman)
github.com/traviskaufman/co-talk-examples
![Page 2: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/2.jpg)
OutlineDefine the problem
Async control flow in NodeJS
Present the solutionCoroutines (surprise!)
Explore the implementationHow coroutines work under the hood
Coroutine librariesStart using them in your apps today!
(time permitting) Advanced usageSample code showing where coroutines really shine
![Page 3: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/3.jpg)
source: https://onlivetest.files.wordpress.com/2014/06/pyramid-of-doom.jpg
The Problem
![Page 4: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/4.jpg)
Callbacks are UNINTUITIVE
source: http://i.imgur.com/DEg3cPZ.png
![Page 5: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/5.jpg)
Callbacks are UNINTUITIVE
Simple Program: Get GH Username, print out 10 most recently pushed repos
https://github.com/traviskaufman/co-talk-examples/blob/master/01-raw-callbacks.js
![Page 6: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/6.jpg)
Callbacks are UNINTUITIVE
Simple Program: Get GH Username, print out 10 most recently pushed repos
https://github.com/traviskaufman/co-talk-examples/blob/master/01-raw-callbacks.js
Code duplication
![Page 7: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/7.jpg)
Callbacks are UNINTUITIVE
Simple Program: Get GH Username, print out 10 most recently pushed repos
https://github.com/traviskaufman/co-talk-examples/blob/master/01-raw-callbacks.js
Code duplication
“Diagonal Development” / Pyramid of Doom / Callback Hell / etc
![Page 8: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/8.jpg)
Callbacks are UNINTUITIVE
Simple Program: Get GH Username, print out 10 most recently pushed repos
https://github.com/traviskaufman/co-talk-examples/blob/master/01-raw-callbacks.js
Code duplication
Refactoring callbacks means
jumping around code to see logical
flow of execution :((
“Diagonal Development” / Pyramid of Doom / Callback Hell / etc
![Page 9: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/9.jpg)
https://github.com/traviskaufman/co-talk-examples/blob/master/02-async-lib-callbacks.js
Callbacks are UNINTUITIVEThe “solution”: use a library (e.g. caolan/async, a.k.a. the jQuery of NodeJS)
![Page 10: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/10.jpg)
Callbacks are UNINTUITIVEThe “solution”: use a library (e.g. caolan/async, a.k.a. the jQuery of NodeJS)
Only have to handle this in one place! :D
https://github.com/traviskaufman/co-talk-examples/blob/master/02-async-lib-callbacks.js
![Page 11: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/11.jpg)
Callbacks are UNINTUITIVEThe “solution”: use a library (e.g. caolan/async, a.k.a. the jQuery of NodeJS)
Need to be familiar with “async.waterfall”
API Change to accommodate lib usage?
Only have to handle this in one place! :D
https://github.com/traviskaufman/co-talk-examples/blob/master/02-async-lib-callbacks.js
![Page 12: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/12.jpg)
Promises to the Rescue!
https://github.com/traviskaufman/co-talk-examples/blob/master/03-raw-promises.js
No triangles/pyramids/hells/doom/etc.
Error handling separated from general logic
![Page 13: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/13.jpg)
Promises to the Rescue! but...
https://github.com/traviskaufman/co-talk-examples/blob/master/03-raw-promises.js
No triangles/pyramids/hells/doom/etc.
Error handling separated from general logic
API Weirdness still...
Still requires handler functions for promise settling
![Page 14: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/14.jpg)
Can We Do Better?
Readability of synchronous code
I/O Efficiency of Asynchronous Code
![Page 15: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/15.jpg)
YES! Introducing Coroutines
https://github.com/traviskaufman/co-talk-examples/blob/master/04-co-promises.js
![Page 16: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/16.jpg)
YES! Introducing Coroutines
● coroutine(gen: GeneratorFunction) => Promise
● generator function yields Promises
● values from resolved promises are assigned
● errors from rejected promises are thrown within generator○ note: could use try/catch inside generator to call handleError()
● Returns Promise for easy interop with other async code
● Best of both worlds! Readability/Intuitiveness + Efficiency/Non-blocking I/O
https://github.com/traviskaufman/co-talk-examples/blob/master/04-co-promises.js
![Page 17: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/17.jpg)
F*CK YEAHsource:
http://3.bp.blogspot.com/-
IYYJ3t1g8hA/ToJtrJegK4I/AA
AAAAAAAUg/qTG1Jh50PsY/s
1600/1264744915828.jpg
![Page 18: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/18.jpg)
Coroutines = “Cooperative Routines”
Cooperative threads are
responsible for explicitly telling
executor when they should be
suspended
Differs from preemptive threads
which rely on executor to
suspend/resume them
Reference (Java-based):
http://www.cafeaulait.org/course/
week11/32.html
https://www.cs.mtu.edu/~shene/NSF-3/e-Book/FUNDAMENTALS/thread-yield.jpg
![Page 19: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/19.jpg)
Coroutines = “Cooperative Routines”
Generators provide cooperation
through the yield keyword
Explicitly tells IO-Loop (uv,
etc.) to suspend execution
Promises provide the routines
Scheduled and run
asynchronously by IO-Loop
Generators + Promises =
Cooperation + Routines =
Coroutines!
https://www.cs.mtu.edu/~shene/NSF-3/e-Book/FUNDAMENTALS/thread-yield.jpg
yield
new Promise(...)
![Page 20: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/20.jpg)
A Simple Implementation
< 25 SLOC!
![Page 21: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/21.jpg)
Coroutine Libraries: tj/co
My personal favorite
Supports thunks as well as promises
Supports yielding arrays/objects
(Promise.race), as well as generators
(delegation)
https://github.com/tj/co
![Page 22: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/22.jpg)
Coroutine Libraries: mozilla/task.js
Similar to co
Very powerful built-in scheduler
Adds cancellation to promises
Makes coroutines look a lot like thread-based
scheduling
http://taskjs.org/
![Page 23: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/23.jpg)
“But wait, I need ES2015 for this!”
Use babelJS (https://babeljs.io/) to transpile
your code!Use the --harmony-generators flag with
v0.11+ to enable generators (or just --
harmony)
Check out petkaantonov/bluebird for an
awesome promise polyfill/superset.
![Page 24: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/24.jpg)
Advanced Example: “Retry” with exponential backoff
![Page 25: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/25.jpg)
Advanced Example: DB Cursoring
![Page 26: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/26.jpg)
Additional Resources
MDN reference for generator functions
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
Awesome Promise tutorial from HTML5Rocks
http://www.html5rocks.com/en/tutorials/es6/promises/
“Promises and Generators: Control Flow Utopia” - Great presentation by Forbes Lindesay
http://pag.forbeslindesay.co.uk/#/
“No Promises: Asynchronous Javascript with only generators”
http://www.2ality.com/2015/03/no-promises.html
Axel Rauschmayer takes it one step further and shows how you can use generators to write
async code without the need for promises. Super interesting stuff!
![Page 27: Dead-Simple Async Control Flow with Coroutines](https://reader034.vdocuments.net/reader034/viewer/2022042708/58aad84f1a28ab27178b4e7f/html5/thumbnails/27.jpg)
THANK YOU SO MUCH! :D