Promises generatorscallbacks

486 views
440 views

Published on

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.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
486
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
4
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Promises generatorscallbacks

  1. 1. Promises, Generators & Callbacks! Oh my!
  2. 2. Writing asynchronous code is hard
  3. 3. asynchronous code is difficult to read
  4. 4. asynchronous code is difficult to write
  5. 5. asynchronous code is difficult to maintain
  6. 6. Mike Frey
  7. 7. Why is writing asynchronous code hard?
  8. 8. Composition
  9. 9. Patterns
  10. 10. Callbacks
  11. 11. Promises
  12. 12. Generators
  13. 13. Now entering Nerd War territory
  14. 14. Goals
  15. 15. Callbacks vs Promises vs Generators
  16. 16. Callbacks vs Promises vs Generators x x
  17. 17. No Winner
  18. 18. Unbiased
  19. 19. Informative
  20. 20. Callbacks
  21. 21. How do they work?
  22. 22. Continuation Passing
  23. 23. Pass a function to another function
  24. 24. Ask for work now Handle result later
  25. 25. askForWork(function(err, res) { // handle result later })
  26. 26. Where are they used?
  27. 27. Everywhere
  28. 28. Node.js core
  29. 29. User-land
  30. 30. Even Promises
  31. 31. Benefits
  32. 32. Simple. Easy to use. Prolific. Fast.
  33. 33. Problems
  34. 34. Error Handling
  35. 35. try{} catch(){}
  36. 36. try{} catch(){}
  37. 37. try { doWork(function(res) { // handle result }) } catch (err) { // handle error }
  38. 38. ! doWork(function(err, res) { // handle error // handle result }) ! !
  39. 39. Homework! read this: ! joyent.com/developers/ node/design/errors
  40. 40. Z͈A͡ ̼͔̭͖͕̲ L͝ ͙͖̱ G̠͍̤̠͕ O͢ ̬̫ Z͗̒͊̅ͫ̎ ̩̲̤͙̟ Ả͒͐̚ ̥̞̥͜ L̀͊ͬ͡ ̮̲Ğͥ̈ͩ̓͒ ͕̘͉ O͍̼̘͇͔̠͐ !̓̾̆ͪ͆̚͞
  41. 41. asynchronous or synchronous never both
  42. 42. Fix your API: process.nextTick() setImmediate()
  43. 43. Fix their API: dezalgo
  44. 44. Callback Hell
  45. 45. Composition problem
  46. 46. Now Later
  47. 47. Now Later Later-er
  48. 48. Now Later Later-er Later-er-er
  49. 49. Now Later Later-er Later-er-er Later-er-er-er
  50. 50. 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)
  51. 51. Now Later Later-er Later-er-er Later-er-er-er
  52. 52. Now Later Later-er Later-er-er Later-er-er-er
  53. 53. getA(function() { getB(function() { getC(function() { // do something }) }) })
  54. 54. function handleA() { getB(handleB) } function handleB() { getC(handleC) } function handleC() { // do something } getA(handleA)
  55. 55. async module
  56. 56. async.waterfall([ getA, getB, getC ], function(err, result) { // do something })
  57. 57. Callbacks ! Simple. Everywhere. Be careful.
  58. 58. Promises
  59. 59. How do they work?
  60. 60. Eventual Result
  61. 61. .then()
  62. 62. var promise = doSomething() promise.then( function (result) { // success callback }, function (error) { // error callback })
  63. 63. Now Later success Later failure
  64. 64. Where are they used?
  65. 65. jQuery AngularJS Ember User-land
  66. 66. Chrome 32 Firefox 29 Opera 19 Node.js 0.11.13
  67. 67. Benefits
  68. 68. Composition: Chaining & Error handling
  69. 69. .then() .then() .then()
  70. 70. Now Later success Later-er success Later-er-er success Later-er-er-er success
  71. 71. function addOne(num) { return new Promise( function(resolve, reject) { resolve(num+1) }) } ! addOne(0) .then(addOne) .then(addOne) .then(addOne) .then(console.log)
  72. 72. function addOne(num) { return num+1 } ! var p = new Promise( function(res, rej) { res(0) }) .then(addOne) .then(addOne) .then(addOne) .then(console.log)
  73. 73. Rejections bubble
  74. 74. Errors bubble
  75. 75. Now Later success Later-er success Later-er-er success Any failure
  76. 76. getSpeakers('MidwestJS') .then(getGithubUsers) .then(getPublicRepos) .then(listRepos, handleError)
  77. 77. Problems
  78. 78. Slow
  79. 79. Slow
  80. 80. Incompatible Proposals & Implementations
  81. 81. jQuery vs everyone else
  82. 82. Promises ! Composable. Eventual Result.
  83. 83. Generators
  84. 84. What are they?
  85. 85. How do they work?
  86. 86. function*
  87. 87. function* tick() { ! ! } ! ! ! !
  88. 88. function* tick() { ! ! } ! var itr = tick() ! !
  89. 89. function* tick() { ! ! } ! var itr = tick() itr.next() !
  90. 90. function* tick() { yield 42 ! } ! var itr = tick() itr.next().value // 42 !
  91. 91. yield
  92. 92. function* tick() { yield 42 yield 43 } ! var itr = tick() itr.next().value // 42 itr.next().value // 43 itr.next().done // true
  93. 93. function* tick() { var x = yield var y = yield } ! var itr = tick() itr.next() itr.next(42) // x becomes 42 itr.next(43) // y becomes 43
  94. 94. function* tick() { var num = 0 while (!(yield num++)); } ! var itr = tick() itr.next().value // 0 itr.next().value // 1 itr.next().value // 2
  95. 95. function* tick() { var num = 0 while (!(yield num++)); } ! var itr = tick() itr.next().value // 0 itr.next().value // 1 itr.next(true).done // true
  96. 96. Replacing callbacks
  97. 97. function delay(time, callback) { setTimeout(function() { callback('Slept for ' + time) }, time) }
  98. 98. function delayThings() { delay(1000, function(result1) { console.log(result1) delay(1200, function(result2) { console.log(result2) }) }) } // Slept for 1000 // Slept for 1200
  99. 99. function* delayThings() { var results1 = yield delay(1000) console.log(results1) ! var results2 = yield delay(1200) console.log(results2) }
  100. 100. function run(generator) { function resume(value) { itr.next(value) } var itr = generator(resume) itr.next() }
  101. 101. function* delayThings() { var results1 = yield delay(1000) console.log(results1) ! var results2 = yield delay(1200) console.log(results2) } !
  102. 102. function* delayThings(resume) { var results1 = yield delay(1000, resume) console.log(results1) ! var results2 = yield delay(1200, resume) console.log(results2) } ! run(delayThings)
  103. 103. More callbacks?
  104. 104. thunkify
  105. 105. // 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) } } }
  106. 106. delay = thunkify(delay) ! var thunk = delay(1000) ! thunk(function(result) { console.log(result) })
  107. 107. function run(generator) { function resume(value) { itr.next(value) } var itr = generator(resume) itr.next() } !
  108. 108. function run(generator) { function resume(ret) { var obj = itr.next(ret) if (obj.done) return obj.value(resume) } var itr = generator() resume() }
  109. 109. function* delayThings() { var results1 = yield delay(1000) console.log(results1) ! var results2 = yield delay(1200) console.log(results2) } ! run(delayThings)
  110. 110. yield Now Later
  111. 111. yield Now yield Later Later-er
  112. 112. yield Now yield Later yield Later-er Later-er-er
  113. 113. yield Now yield Later yield Later-er yield Later-er-er Later-er-er-er …
  114. 114. co
  115. 115. var delayThings = co(function*() { var results1 = yield delay(1000) console.log(results1) ! var results2 = yield delay(1200) console.log(results2) }) ! delayThings()
  116. 116. var delayThings = co(function*() { var delays = [delay(1000), delay(1200)] var results = yield delays ! console.log(results[0]) console.log(results[1]) }) ! delayThings()
  117. 117. Where are they used?
  118. 118. co koa User-land
  119. 119. Firefox 31 Chrome (flag) Node.js v0.11.10 (flag) Opera (flag)
  120. 120. Benefits
  121. 121. Feels synchronous
  122. 122. try{} catch(){}
  123. 123. New cool
  124. 124. Problems
  125. 125. Support
  126. 126. regenerator facebook.github.io/regenerator/
  127. 127. traceur github.com/google/traceur-compiler
  128. 128. Immature implementations
  129. 129. Generators ! yield statement. Pausable function*. Built for iterators.
  130. 130. Writing asynchronous code is hard
  131. 131. But it doesn’t have to be!
  132. 132. Call to action
  133. 133. Explore
  134. 134. Streams http://nodestreams.com http://highlandjs.org
  135. 135. Thank you!
  136. 136. Questions? ! References available here: github.com/mikefrey/cpg-talk

×