Download - Promises generatorscallbacks

Transcript
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