Promises generatorscallbacks

136
Promises, Generators & Callbacks! Oh my!

description

Many developers new to Node.js struggle with writing asynchronous code in a clean, concise, easy to maintain manner. There are many strategies for managing and preventing 'callback hell' in Node.js. We'll walk through many of those strategies, from Promises to Generators to flow control libraries, and show that with a bit of forethought, writing asynchronous code in Javascript and Node.js can be easy and maintainable.

Transcript of Promises generatorscallbacks

Page 1: Promises generatorscallbacks

Promises, Generators &

Callbacks! Oh my!

Page 2: Promises generatorscallbacks

Writing asynchronous code is hard

Page 3: Promises generatorscallbacks

asynchronous code is difficult to read

Page 4: Promises generatorscallbacks

asynchronous code is difficult to write

Page 5: Promises generatorscallbacks

asynchronous code is difficult to maintain

Page 6: Promises generatorscallbacks

Mike Frey

Page 7: Promises generatorscallbacks

Why is writing asynchronous

code hard?

Page 8: Promises generatorscallbacks

Composition

Page 9: Promises generatorscallbacks

Patterns

Page 10: Promises generatorscallbacks

Callbacks

Page 11: Promises generatorscallbacks

Promises

Page 12: Promises generatorscallbacks

Generators

Page 13: Promises generatorscallbacks

Now entering Nerd War territory

Page 14: Promises generatorscallbacks

Goals

Page 15: Promises generatorscallbacks

Callbacks vs

Promises vs

Generators

Page 16: Promises generatorscallbacks

Callbacks vs

Promises vs

Generators

xx

Page 17: Promises generatorscallbacks

No Winner

Page 18: Promises generatorscallbacks

Unbiased

Page 19: Promises generatorscallbacks

Informative

Page 20: Promises generatorscallbacks

Callbacks

Page 21: Promises generatorscallbacks

How do they work?

Page 22: Promises generatorscallbacks

Continuation Passing

Page 23: Promises generatorscallbacks

Pass a function

to another function

Page 24: Promises generatorscallbacks

Ask for work nowHandle result later

Page 25: Promises generatorscallbacks

askForWork(function(err, res) { // handle result later})

Page 26: Promises generatorscallbacks

Where are they used?

Page 27: Promises generatorscallbacks

Everywhere

Page 28: Promises generatorscallbacks

Node.js core

Page 29: Promises generatorscallbacks

User-land

Page 30: Promises generatorscallbacks

Even Promises

Page 31: Promises generatorscallbacks

Benefits

Page 32: Promises generatorscallbacks

Simple. Easy to use.

Prolific. Fast.

Page 33: Promises generatorscallbacks

Problems

Page 34: Promises generatorscallbacks

Error Handling

Page 35: Promises generatorscallbacks

try{} catch(){}

Page 36: Promises generatorscallbacks

try{} catch(){}

Page 37: Promises generatorscallbacks

try { doWork(function(res) { // handle result })}catch (err) { // handle error }

Page 38: Promises generatorscallbacks

!

doWork(function(err, res) { // handle error // handle result })!

!

Page 39: Promises generatorscallbacks

Homework! read this:

!

joyent.com/developers/node/design/errors

Page 40: Promises generatorscallbacks

ZA L GO Z

Ả L Ğ O !

Page 41: Promises generatorscallbacks

asynchronous or

synchronous never both

Page 42: Promises generatorscallbacks

Fix your API: process.nextTick()

setImmediate()

Page 43: Promises generatorscallbacks

Fix their API: dezalgo

Page 44: Promises generatorscallbacks

Callback Hell

Page 45: Promises generatorscallbacks

Composition problem

Page 46: Promises generatorscallbacks

NowLater

Page 47: Promises generatorscallbacks

NowLaterLater-er

Page 48: Promises generatorscallbacks

NowLaterLater-erLater-er-er

Page 49: Promises generatorscallbacks

NowLaterLater-erLater-er-erLater-er-er-er

Page 50: Promises generatorscallbacks

There’s nothing forcing you to write ten levels of nested callbacks, but the pattern does make it easy for you to do so.

- Raymond Julin (paraphrased)

Page 51: Promises generatorscallbacks

NowLaterLater-erLater-er-erLater-er-er-er

Page 52: Promises generatorscallbacks

NowLaterLater-erLater-er-erLater-er-er-er

Page 53: Promises generatorscallbacks

getA(function() { getB(function() { getC(function() { // do something }) })})

Page 54: Promises generatorscallbacks

function handleA() { getB(handleB)}function handleB() { getC(handleC)}function handleC() { // do something}getA(handleA)

Page 55: Promises generatorscallbacks

async module

Page 56: Promises generatorscallbacks

async.waterfall([ getA, getB, getC ], function(err, result) { // do something })

Page 57: Promises generatorscallbacks

Callbacks !

Simple. Everywhere. Be careful.

Page 58: Promises generatorscallbacks

Promises

Page 59: Promises generatorscallbacks

How do they work?

Page 60: Promises generatorscallbacks

Eventual Result

Page 61: Promises generatorscallbacks

.then()

Page 62: Promises generatorscallbacks

var promise = doSomething()promise.then( function (result) { // success callback }, function (error) { // error callback })

Page 63: Promises generatorscallbacks

NowLater successLater failure

Page 64: Promises generatorscallbacks

Where are they used?

Page 65: Promises generatorscallbacks

jQuery AngularJS

Ember User-land

Page 66: Promises generatorscallbacks

Chrome 32 Firefox 29 Opera 19

Node.js 0.11.13

Page 67: Promises generatorscallbacks

Benefits

Page 68: Promises generatorscallbacks

Composition: Chaining &

Error handling

Page 69: Promises generatorscallbacks

.then()

.then()

.then()

Page 70: Promises generatorscallbacks

NowLater successLater-er successLater-er-er successLater-er-er-er success

Page 71: Promises generatorscallbacks

function addOne(num) { return new Promise( function(resolve, reject) { resolve(num+1) })}!

addOne(0) .then(addOne) .then(addOne) .then(addOne) .then(console.log)

Page 72: Promises generatorscallbacks

function addOne(num) { return num+1}!

var p = new Promise( function(res, rej) { res(0) }) .then(addOne) .then(addOne) .then(addOne) .then(console.log)

Page 73: Promises generatorscallbacks

Rejections bubble

Page 74: Promises generatorscallbacks

Errors bubble

Page 75: Promises generatorscallbacks

NowLater successLater-er successLater-er-er successAny failure

Page 76: Promises generatorscallbacks

getSpeakers('MidwestJS') .then(getGithubUsers) .then(getPublicRepos) .then(listRepos, handleError)

Page 77: Promises generatorscallbacks

Problems

Page 78: Promises generatorscallbacks

Slow

Page 79: Promises generatorscallbacks

Slow

Page 80: Promises generatorscallbacks

Incompatible Proposals &

Implementations

Page 81: Promises generatorscallbacks

jQuery vs

everyone else

Page 82: Promises generatorscallbacks

Promises !

Composable. Eventual Result.

Page 83: Promises generatorscallbacks

Generators

Page 84: Promises generatorscallbacks

What are they?

Page 85: Promises generatorscallbacks

How do they work?

Page 86: Promises generatorscallbacks

function*

Page 87: Promises generatorscallbacks

function* tick() {!

!

}!

!

!

!

Page 88: Promises generatorscallbacks

function* tick() {!

!

}!

var itr = tick()!

!

Page 89: Promises generatorscallbacks

function* tick() {!

!

}!

var itr = tick()itr.next()!

Page 90: Promises generatorscallbacks

function* tick() { yield 42!

}!

var itr = tick()itr.next().value // 42!

Page 91: Promises generatorscallbacks

yield

Page 92: Promises generatorscallbacks

function* tick() { yield 42 yield 43}!

var itr = tick()itr.next().value // 42itr.next().value // 43itr.next().done // true

Page 93: Promises generatorscallbacks

function* tick() { var x = yield var y = yield}!

var itr = tick()itr.next()itr.next(42) // x becomes 42itr.next(43) // y becomes 43

Page 94: Promises generatorscallbacks

function* tick() { var num = 0 while (!(yield num++));}!

var itr = tick()itr.next().value // 0itr.next().value // 1itr.next().value // 2

Page 95: Promises generatorscallbacks

function* tick() { var num = 0 while (!(yield num++));}!

var itr = tick()itr.next().value // 0itr.next().value // 1itr.next(true).done // true

Page 96: Promises generatorscallbacks

Replacing callbacks

Page 97: Promises generatorscallbacks

function delay(time, callback) { setTimeout(function() { callback('Slept for ' + time) }, time)}

Page 98: Promises generatorscallbacks

function delayThings() { delay(1000, function(result1) { console.log(result1) delay(1200, function(result2) { console.log(result2) }) })}// Slept for 1000// Slept for 1200

Page 99: Promises generatorscallbacks

function* delayThings() { var results1 = yield delay(1000) console.log(results1)!

var results2 = yield delay(1200) console.log(results2)}

Page 100: Promises generatorscallbacks

function run(generator) { function resume(value) { itr.next(value) } var itr = generator(resume) itr.next()}

Page 101: Promises generatorscallbacks

function* delayThings() { var results1 = yield delay(1000) console.log(results1)!

var results2 = yield delay(1200) console.log(results2)}!

Page 102: Promises generatorscallbacks

function* delayThings(resume) { var results1 = yield delay(1000, resume) console.log(results1)!

var results2 = yield delay(1200, resume) console.log(results2)}!

run(delayThings)

Page 103: Promises generatorscallbacks

More callbacks?

Page 104: Promises generatorscallbacks

thunkify

Page 105: Promises generatorscallbacks

// simplified from// https://github.com/visionmedia/node-thunkify

!function thunkify(fn){ return function(){ var args = Array.prototype.slice.call(arguments) return function(done){ args.push(function(){ done.apply(null, arguments) }) fn.apply(null, args) } }}

Page 106: Promises generatorscallbacks

delay = thunkify(delay)!

var thunk = delay(1000)!

thunk(function(result) { console.log(result)})

Page 107: Promises generatorscallbacks

function run(generator) { function resume(value) { itr.next(value) } var itr = generator(resume) itr.next()}!

Page 108: Promises generatorscallbacks

function run(generator) { function resume(ret) { var obj = itr.next(ret) if (obj.done) return obj.value(resume) } var itr = generator() resume()}

Page 109: Promises generatorscallbacks

function* delayThings() { var results1 = yield delay(1000) console.log(results1)!

var results2 = yield delay(1200) console.log(results2)}!

run(delayThings)

Page 110: Promises generatorscallbacks

yield Now Later

Page 111: Promises generatorscallbacks

yield Now yield Later Later-er

Page 112: Promises generatorscallbacks

yield Now yield Later yield Later-er Later-er-er

Page 113: Promises generatorscallbacks

yield Now yield Later yield Later-er yield Later-er-er Later-er-er-er …

Page 114: Promises generatorscallbacks

co

Page 115: Promises generatorscallbacks

var delayThings = co(function*() { var results1 = yield delay(1000) console.log(results1)!

var results2 = yield delay(1200) console.log(results2)})!

delayThings()

Page 116: Promises generatorscallbacks

var delayThings = co(function*() { var delays = [delay(1000), delay(1200)] var results = yield delays!

console.log(results[0]) console.log(results[1])})!

delayThings()

Page 117: Promises generatorscallbacks

Where are they used?

Page 118: Promises generatorscallbacks

co koa

User-land

Page 119: Promises generatorscallbacks

Firefox 31 Chrome (flag)

Node.js v0.11.10 (flag) Opera (flag)

Page 120: Promises generatorscallbacks

Benefits

Page 121: Promises generatorscallbacks

Feels synchronous

Page 122: Promises generatorscallbacks

try{} catch(){}

Page 123: Promises generatorscallbacks

New cool

Page 124: Promises generatorscallbacks

Problems

Page 125: Promises generatorscallbacks

Support

Page 126: Promises generatorscallbacks

regenerator facebook.github.io/regenerator/

Page 127: Promises generatorscallbacks

traceur github.com/google/traceur-compiler

Page 128: Promises generatorscallbacks

Immature implementations

Page 129: Promises generatorscallbacks

Generators !

yield statement. Pausable function*.

Built for iterators.

Page 130: Promises generatorscallbacks

Writing asynchronous code is hard

Page 131: Promises generatorscallbacks

But it doesn’t

have to be!

Page 132: Promises generatorscallbacks

Call to action

Page 133: Promises generatorscallbacks

Explore

Page 134: Promises generatorscallbacks

Streams http://nodestreams.com

http://highlandjs.org

Page 135: Promises generatorscallbacks

Thank you!

Page 136: Promises generatorscallbacks

Questions? !

References available here: github.com/mikefrey/cpg-talk