Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ES6 Async pattern using generator functions

Deep Focus
October 15, 2014

ES6 Async pattern using generator functions

Check out how generator function can help to fight a "callback hell".

Deep Focus

October 15, 2014
Tweet

More Decks by Deep Focus

Other Decks in Programming

Transcript

  1. All content contained herein is property of Deep Focus. ©2012

    All Rights Reserved. USING GENERATOR FUNCTIONS TECH BREAKFAST ES6 ASYNC PATTERN Anton Boichev OCTOBER 15, 2014
  2. AGENDA 1.  What is a “callback hell” 2.  Refresh on

    ES6 generator functions 3.  Async pattern using generator functions 4.  Node’s “Co” library 5.  Node’s popular Express.js successor Koa.js 6.  Other async libraries, performance complexity and stack trace accuracy. 7.  Sources / Credits
  3. PAGE 3 25 JANUARY 2012 What is a “callback hell”

    x = getData(); y = getMoreData(x); z = getMoreData(y); getData(function(x){ getMoreData(x, function(y){ getMoreData(y, function(z){ ... }); }); }); It  happens  when  you  have  lots  of  callback  func4ons  in  your  code!   It  gets  harder  to  work  with  them  the  more  of  them  you  have  in  your  code  and  it  gets  par4cularly  bad   when  you  need  to  do  loops,  try-­‐catch  blocks  and  things  like  that.  
  4. Refresh on ES6 generator functions function *simpleGenerator(){ yield "first"; yield

    "second"; yield "third"; for (var i = 0; i < 3; i++) yield i; } var g = simpleGenerator(); console.log(g.next()); // prints { value: 'first', done: false } console.log(g.next()); // prints { value: 'second', done: false } console.log(g.next()); // prints { value: 'third', done: false } console.log(g.next()); // prints { value: 0, done: false } console.log(g.next()); // prints { value: 1, done: false } console.log(g.next()); // prints { value: 2, done: false } console.log(g.next()); // prints { value: undefined, done: true } console.log(g.next()); // prints { value: undefined, done: true }
  5. PAGE 5 25 JANUARY 2012 generator functions (continued) function *fibonacci()

    { var i = 0, j = 1; for(;;) { yield i; var t = i; i = j; j += t; } } for (n of fibonacci()) { if (n > 1000) { break; } console.log(n); }
  6. Async pattern in simplest form: var req = require('request'); function

    getAsync(url) { req(url, function (error, response) { it.next(response); }); } function *main() { var result1 = yield getAsync('http://google.com'); console.log('Request 1: ' + result1.body.length); var result2 = yield getAsync('http://bing.com'); console.log('Request 2: ' + result2.body.length); } var it = main(); it.next();
  7. Nodes co.js library var co = require('co'); var thunkify =

    require('thunkify'); var request = require('request'); var get = thunkify(request.get); co(function *(){ var a = yield get('http://google.com'); var b = yield get('http://yahoo.com'); var c = yield get('http://cloudup.com'); console.log(a[0].statusCode); console.log(b[0].statusCode); console.log(c[0].statusCode); })() co(function *(){ var a = get('http://google.com'); var b = get('http://yahoo.com'); var c = get('http://cloudup.com'); var res = yield [a, b, c]; console.log(res[0].statusCode); console.log(res[1].statusCode); console.log(res[2].statusCode); })() // Error handling co(function *(){ try { var res = yield get('http://badhost.invalid'); console.log(res); } catch(e) { console.log(e.code) // ENOTFOUND } })()
  8. Koa.js TJ  Holowaychuk  is  s4ll  maintaining  this  project  (even  aCer

     switching  to  Go)   var koa = require('koa'); var app = koa(); app.use(function *(){ this.body = 'Hello World'; }); app.listen(3000);
  9. Koa.js (continued) var compose = require('koa-compose'); var koa = require('koa');

    var app = module.exports = koa(); // x-response-time function *responseTime(next){ var start = new Date; yield next; var ms = new Date - start; this.set('X-Response-Time', ms + 'ms'); } // logger function* logger(next){ var start = new Date; yield next; var ms = new Date - start; if ('test' != process.env.NODE_ENV) { console.log('%s %s - %s', this.method, this.url, ms); } } // response function* respond(next){ yield next; if ('/' != this.url) return; this.body = 'Hello World'; } // composed middleware var all = compose([ responseTime, logger, respond ]); app.use(all); if (!module.parent) app.listen(3000);
  10. Other async libraries, performance complexity and stack trace accuracy. name

      source  maps   stack  traces   total   fibrous.js   5   5   10   src-­‐streamline._js   4   5   9   original.js   5   4   9   flaNened*.js   5   4   9   rx.js   5   4   9   catcher.js   5   3   8   promiseishQ.js   5   3   8   qasync.js   4   3   7   genny.js   4   3   7   async.js   5   1   6   promiseish.js   5   1   6   promises.js   5   1   6   suspend.js   4   1   5   gens.js   4   1   5   co.js   4   1   5  
  11. Sources / Credits ¤  h"p://spion.github.io/posts/analysis-­‐generators-­‐and-­‐other-­‐async-­‐pa"erns-­‐node.html   ¤  h"p://davidwalsh.name/async-­‐generators   ¤ 

    h"ps://github.com/visionmedia/co   ¤  h"ps://github.com/koajs/koa   ¤  h"ps://developer.mozilla.org/en-­‐US/docs/Web/JavaScript/Guide/Iterators_and_Generators   ¤  h"p://stackoverflow.com/quesGons/25098066/what-­‐is-­‐callback-­‐hell-­‐and-­‐how-­‐and-­‐why-­‐rx-­‐solves-­‐it   ¤  h"ps://medium.com/@tjholowaychuk