nodejs design patterns 130602183400 phpapp02

Upload: chaitu215

Post on 05-Jul-2018

224 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    1/76

    Node.js PatternsFor the Discerning Developer

    C. Aaron Cois, Ph.D. :: Carnegie Mellon University, SE

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    2/76

    Me

    !aaroncois

    """.codehenge.net

    gith#$.co%&cacois

    Disclaimer: Though I am an employee of the Software Engineering Institute at Carnegie Mellon University,this work was not fune !y the SEI an oes not re"ect the work or opinions of the SEI or its customers#

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    3/76

    'et(s tal) a$o#t

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    4/76

    Node.js *asics

    •  +avaScript

    • Asynchrono#s

    • Non$loc)ing &-

    • Eventdriven

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    5/76

    So, +avaScript

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    6/76

     /he *asics

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    7/76

    Prototype$ased Progra%%ing

    •  +avaScript has no classes

    • nstead, 0#nctions de1ne o$jects

    function Person() {}

    var p = new Person();

    %age: http:&&tech2.in.co%&0eat#res&ga%ing&1ve"ac)yga%inghard"aretoloo)0or"ardto&345672

    $rototype

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    8/76

    Classless Progra%%ing

    8hat do classes do 0or #s

    • De1ne local scope & na%espace

    • Allo" private attri$#tes & %ethods

    • Encaps#late code

    -rgani9e applications in an o$jectoriented "ay

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    9/76

    Prototype$ased Progra%%ing

     

    function Person(firstname, lastname){  this.firstnam e =  firstname;  this.lastnam e =  lastname;

     } 

    var p =  new Person(“Philip”, “Fry”);

    8hat else can do that

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    10/76

    Prototype nheritance 

    function Person(firstname, lastname){  this.firstnam e =  firstname;  this.lastnam e =  lastname; }  %% Create new class

     Employee = Person; %%Inherit from superclass

     Employee.prototype =  {  marital_status: 'single', 

    salute: function() {  return 'M y nam e is ' + this.firstname;  } }

     var p =  new Employee (“Philip”, “Fry”);

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    11/76

    8atch o#t

     function Person(firstname, lastname){  this.firstnam e =  firstname;  this.lastnam e =  lastname; }  %% Create new class Employee = Person; %%Inherit from superclass

     Employee.prototype =  {  marital_status: 'single', 

    salute: function() {  return 'M y nam e is ' + this.firstname;  } }

     var p =  new Employee (“Philip”, “Fry”);

     /he ;ne"( is very i%portant

    0 yo# 0orget, yo#r ne" o$ject"ill have glo$al scope internally

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    12/76

    Another option

     function Person(firstname, lastname){  this.firstnam e =  firstname;  this.lastnam e =  lastname; } Employee = Person; %%Inherit from superclass

     Employee.prototype =  {  marital_status: 'single', 

    salute: function() {  return 'M y nam e is ' + this.firstname;

      } }

     var p =  Object.create(Employee); p.firstname =  'Philip'; p.lastname =  'Fry';

    8or)s, $#t yo# can(t initiali9eattri$#tes in constr#ctor

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    13/76

    AntiPattern: +avaScript %ports

    • Spread code aro#nd 1les

    • 'in) li$raries

    • No "ay to %aintain private localscope&state&na%espace

    'eads to: – Na%e collisions

     – Unnecessary access

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    14/76

    Pattern: Mod#les

    • An elegant "ay o0 encaps#lating andre#sing code

    • Adapted 0ro%

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    15/76

    Mod#les in the 8ild

     var http =  require('http'),

      io =  require('socketio'),

      _ =  require('!n"erscore');

    0 yo#(ve progra%%ed in Node, this

    loo)s 0a%iliar

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    16/76

    Anato%y o0 a %od#le

      var privateVal =  '# am Pri$ate%';

     

    module.e&ports =  {  answer: , 

    add: function(x, y) {

      return x +  y;

      }

      }

    %y%od#le.js

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    17/76

    Usage

     

    mod =  require('m ym o"!le');

     

    console.log('*he ans er: '+ mod.ans er);

     

    var sum =  mod.a""(,);

     console.log('-!m : ' +  sum);

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    18/76

    Mod#les are #sed every"here

      %% User moel  var mongoose =  require('m ongoose')

      , Schema =  mongoose.-chem a;

     

    var userSchema =  new Schema({

      nam e: {type: String, required: true},

      email: {type: String, required: true},  githubid: String,

      twitterid: String,

      dateCreated: {type: Date, default: Date.no }

      });

     

    userSchema.m etho"s.$ali"Passor" =  function validPass(pass) {

       %% valiate passwor&

      }

     

    module.e&ports =  mongoose.m o"el('.ser', userSchema);

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    19/76

    My con1g 1les Mod#les.

      var config =  require('config/s');

     

    console.log('0onfig!re" !ser is: ' + config.user);

      module.e&ports =  {

      user: 'm a!ricem oss'

      }

    con1g.js

    app.js

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    20/76

    Asynchrono#s

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    21/76

    Asynchrono#s Progra%%ing

    • Node is entirely asynchrono#s

    •  

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    22/76

    Event 'oop

    Node.jsEvent

    'oop

    Node app

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    23/76

    Event 'oop

    Node.jsEvent

    'oop

    Node apps pass asynctas)s to the eventloop, along "ith a

    call$ac)

    >0#nction, call$ac)?

    Node app

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    24/76

    Event 'oop

    Node.jsEvent

    'oop

     /he event loop e@ciently%anages a thread pool andeec#tes tas)s e@cientlyB

     /hread4

     /hread2

     /hreadn

    B /as) 4

     /as) 2

     /as) 3

     /as) 7

    et#rn 4

    Call$ac)4>?

    Band eec#tes eachcall$ac) as tas)s co%plete

    Node app

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    25/76

    Async &-

     /he 0ollo"ing tas)s sho#ld $e doneasynchrono#sly, #sing the event loop:

    • &- operations

    • eavy co%p#tation

    Anything re#iring $loc)ing

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    26/76

     

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    27/76

    Antipattern: Synchrono#s Code

      for (var i =  1; i 2  311111; i+ + ){

      4o anything

     }

     

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    28/76

    Antipattern: Synchrono#s Code

    *#t "hy "o#ld yo# do that

    ood #estion.

    *#t in other lang#ages >Python?, yo# %ay do this:

     

    for file in files:  f = open(file, 5r6)  print frea"line()

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    29/76

    Antipattern: Synchrono#s Code

     /he Node.js e#ivalent is:

    *ased on ea%ples 0ro%: https:&&gith#$.co%&node$its&distilled

     var fs =  require('fs');

     

    for (var i =  1;i 2  files.length;i+ + ){  data = fs.rea"File-ync(files7i8);  console.log(data);

     }

    Band it "ill ca#se severe per0or%ancepro$le%s

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    30/76

    Pattern: Async &-

     

    fs =  require('fs');

     

    fs.rea"File('f3t&t','!tf9',function(err,data){

      if  (err) {

      // handle error

      }

      console.log(data);

     });

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    31/76

    Async &-

     

    fs =  require('fs');

     

    fs.rea"File('f3t&t','!tf9',function(err,data){

      if  (err) {

      // handle error

      }

      console.log(data);

     });

    Anony%o#s, inline call$ac)

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    32/76

    Async &-

     

    fs =  require('fs');

     

    fs.rea"File('f3t&t','!tf9',

      function(err,data){

      if  (err) {

      // handle error

      }

      console.log(data);

      }

     );

    E#ivalent

    synta

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    33/76

    Call$ac) ell

    8hen "or)ing "ith call$ac)s, nestingcan get #ite o#t o0 handB

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    34/76

    Call$ac) ell

    var db =  require('som e"ataasepro$i"er');

     %%get recent posts

    http.get('recentposts', function(req, res) {

      %% open ata!ase connection

      db.open0onnection('host', creds,function(err, conn){  res.param 7'posts'8.forach(post) {

      conn.

      conn.close();

      res.sen"(users718);

      });

      }

      });

    });

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    35/76

    Call$ac) ell

    var db =  require('som e"ataasepro$i"er');

     %%get recent posts

    http.get('recentposts', function(req, res) {

      %% open ata!ase connection

      db.open0onnection('host', creds,function(err, conn){  res.param 7'posts'8.forach(post) {

      conn.

      conn.close();

      res.sen"(users718);

      });

      }

      });

    });

    et recent posts 0ro% "e$service AP

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    36/76

    Call$ac) ell

    var db =  require('som e"ataasepro$i"er');

     %%get recent posts

    http.get('recentposts', function(req, res) {

      %% open ata!ase connection

      db.open0onnection('host', creds,function(err, conn){  res.param 7'posts'8.forach(post) {

      conn.

      conn.close();

      res.sen"(users718);

      });

      }

      });

    });

    -pen connection to D*

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    37/76

    Call$ac) ell

    var db =  require('som e"ataasepro$i"er');

     %%get recent posts

    http.get('recentposts', function(req, res) {

      %% open ata!ase connection

      db.open0onnection('host', creds,function(err, conn){  res.param 7'posts'8.forach(post) {

      conn.

      conn.close();

      res.sen"(users718);

      });

      }

      });

    });

    et #ser 0ro% D* 0or eachpost

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    38/76

    Call$ac) ell

    var db =  require('som e"ataasepro$i"er');

     %%get recent posts

    http.get('recentposts', function(req, res) {

      %% open ata!ase connection

      db.open0onnection('host', creds,function(err, conn){  res.param 7'posts'8.forach(post) {

      conn.

      conn.close();

      res.sen"(users718);

      });

      }

      });

    });

    et#rn #sers

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    39/76

    Call$ac) ell

    var db =  require('som e"ataasepro$i"er');

     %%get recent posts

    http.get('recentposts', function(req, res) {

      %% open ata!ase connection

      db.open0onnection('host', creds,function(err, conn){  res.param 7'posts'8.forach(post) {

      conn.

      conn.close();

      res.sen"(users718);

      });

      }

      });

    });

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    40/76

    AntiPattern: Call$ac) ellfs.rea""ir(source, function(err, files) {

      if  (err) {

      console.log('rror fin"ing files: ' +  err)

      } else {

      files.forach(function(filename, fileIndex) {

      console.log(filename)

      gm(source +  filename).si>e(function(err, values) {

      if  (err) {

      console.log('rror i"entifying file si>e: ' +  err)

      } else {  console.log(filename +  ' : ' +  values)

      aspect =  (values. i"th  values.height)

      widths.forach(function(width, widthIndex) {

      height =  Math.ro!n"(width  aspect)

      console.log('resi>ing ' +  filename +  'to ' +  height +  '&' +  height)

      this.resi>e(width, height).write(destination+ ' 6+ width+ '?6+ filename, function(err){

      if  (err) console.log('rror riting file: ' +  err)

      })  }.in"(this))

      }

      })

      })

      }

    })

    http:&&call$ac)hell.co%&

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    41/76

    Sol#tions

    • Separate anony%o#s call$ac)0#nctions >cos%etic?

    • Async.js

    • Pro%ises

    • enerators

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    42/76

    Pattern:

    Separate Call$ac)s

     

    fs =  require('fs');

     

    callback = function(err,data){  if  (err) {

      // handle error

      }

      console.log(data); }

     fs.rea"File('f3t&t','!tf9',callack);

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    43/76

    Can /#rn /his

     var db =  require('som e"ataasepro$i"er');

     http.get('recentposts', function(req, res){

      db.open0onnection('host',creds,function(err, conn){

      res.param 7'posts'8.forach(post) {  conn.

    post7'!ser'8,function(err,results){

      conn.close();

      res.sen"(results718);

      });

      }

      });

    });

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    44/76

    nto /his

     var db =  require('som e"ataasepro$i"er'); 

    http.get('recentposts', afterRecentPosts);

     

    function afterRecentPosts(req, res) {

      db.open0onnection('host', creds, function(err, conn) {

      afterDBConnected(res, conn);  });

     }

     function afterDBConnected(err, conn) {

      res.param 7'posts'8.forach(post) {

      conn.

      } }

     function afterQuery(err, results) {

      conn.close();

      res.sen"(results718);

     }

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    45/76

     /his is really a Control 'low iss#e

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    46/76

    Pattern: Async.js

    Async.js provides co%%on patterns 0orasync code control Go"

    https:&&gith#$.co%&caolan&async

    Also provides so%e co%%on 0#nctionalprogra%%ing paradig%s

    https://github.com/caolan/asynchttps://github.com/caolan/asynchttps://github.com/caolan/async

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    47/76

    Serial&Parallel F#nctions

    • So%eti%es yo# have linearserial&parallel co%p#tations to r#n,"itho#t $ranching call$ac) gro"th

    F#nction4

    F#nction2

    F#nction3

    F#nction7

    F#nction4

    F#nction2

    F#nction3

    F#nction7

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    48/76

    Serial&Parallel F#nctions

    async.parallel(7

      function(){ ... },

      function(){ ... }

    8, callback); 

    async.series(7

      function(){ ... },  function(){ ... }

    8);

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    49/76

    Serial&Parallel F#nctions

    async.parallel(7

      function(){ ... },

      function(){ ... }

    8, callback); 

    async.series(7

      function(){ ... },  function(){ ... }

    8, callback);

    Single Call$ac)

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    50/76

    8ater0all

    Async. aterfall(7

      function(callack){ ... },

      function(inp!t,callack){ ... },

      function(inp!t,callack){ ... },

    8, callback);

     

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    51/76

    Map

     var arr =  7'file3','file','file@'8;

     

    async.m ap(arr, fs.stat, function(err, results){

       %% results is an array of stats for each (le

      console.log('File stats: ' +  

    JSON.stringify(results));

     });

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    52/76

    Filter

     var arr =  7'file3','file','file@'8;

     

    async.filter(arr, fs.e&ists, function(results){

       %% results is a list of the e)isting (les

      console.log('&isting files: ' +  results);

     });

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    53/76

    8ith great po"erB

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    54/76

    Care0ree

     var fs =  require('fs'); 

    for (var i =  1; i 2  31111; i+ + ) {

      fs.rea"File-ync(filename);

     }

    8ith synchrono#s code, yo# can loop as %#chas yo# "ant:

     /he 1le is opened once each iteration.

     /his "or)s, $#t is slo" and de0eats the point o0

    Node.

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    55/76

    Synchrono#s Doesn(t Scale

    8hat i0 "e "ant to scale to 4H,HHHIconc#rrent #sers

    File &-$eco%es the$ottlenec)

    Users get in along line

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    56/76

    Async to the esc#e

     var fs =  require('fs');

     

    function onRead(err, file) {  if  (err) throw err;

     }

     for (var i =  1; i 2  31111; i+ + ) {

      fs.rea"File(filename, onRead);

     }

    8hat happens i0 do this asyncrono#sly

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    57/76

    #h oh

     /he event loop is fast 

     /his "ill open the 1le 4H,HHH ti%es atonce

     /his is #nnecessaryBand on %ostsyste%s, yo# "ill r#n o#t o0 1ledescriptors

    P tt

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    58/76

    Pattern:

     /he e#est *atch

    • -ne sol#tion is to $atch re#ests

    • Piggy$ac) on eisting re#ests 0orthe sa%e 1le

    • Each 1le then only has one openre#est at a ti%e, regardless o0

    re#esting clients

     // Batching wrapper for fs.readFile()

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    59/76

     var requestBatches = {};

     function batchedReadFile(filename, callback) {

      // Is there already a batch for this file?

      if (filename in requestBatches) {

      // if so, push callback into batch

      requestBatches[filename].push(callback);

      return;

      }

      // If not, start a new request

      var callbacks = requestBatches[filename] = [callback];

      fs.readFile(filename, onRead);

     

    // Flush out the batch on coplete

      function onRead(err, file) {

      delete requestBatches[filename];

      for(var i = 0;i

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    60/76

     var requestBatches = {};

     function batchedReadFile(filename, callback) {

      // Is there already a batch for this file?

      if (filename in requestBatches) {

      // if so, push callback into batch

      requestBatches[filename].push(callback);

      return;

      }

      // If not, start a new request

      var callbacks = requestBatches[filename] = [callback];

      fs.readFile(filename, onRead);

     

    // Flush out the batch on coplete

      function onRead(err, file) {

      delete requestBatches[filename];

      for(var i = 0;i

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    61/76

     var requestBatches = {};

     function batchedReadFile(filename, callback) {

      // Is there already a batch for this file?

      if (filename in requestBatches) {

      // if so, push callback into batch

      requestBatches[filename].push(callback);

      return;

      }

      // If not, start a new request

      var callbacks = requestBatches[filename] = [callback];

      fs.readFile(filename, onRead);

     

    // Flush out the batch on coplete

      function onRead(err, file) {

      delete requestBatches[filename];

      for(var i = 0;i

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    62/76

     var requestBatches = {};

     function batchedReadFile(filename, callback) {

      // Is there already a batch for this file?

      if (filename in requestBatches) {

      // if so, push callback into batch

      requestBatches[filename].push(callback);

      return;

      }

      // If not, start a new request

      var callbacks = requestBatches[filename] = [callback];

      fs.readFile(filename, onRead);

     

    // Flush out the batch on coplete

      function onRead(err, file) {

      delete requestBatches[filename];

      for(var i = 0;i

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    63/76

    Usage

     %%*e+uest the resource -,--- times at once

     for (var i =  1; i 2  31111; i+ + ) {

      batchedReadFile(file, onComplete);

     }

     function onComplete(err, file) {

    if  (err

    ) throw

     err;else console.log('File contents: ' +  file);

     }

    *ased on ea%ples 0ro%: https:&&gith#$.co%&node$its&distilled

    Pattern

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    64/76

    Pattern:

     /he e#est *atch

     /his pattern is e=ective on %any readtype operations, not j#st 1le reads

    Ea%ple: also good 0or "e$ service APcalls

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    65/76

    Shortco%ings

    *atching re#ests is great 0or highre#est spi)es

    -0ten, yo# are %ore li)ely to seesteady re#ests 0or the sa%e reso#rce

     /his $egs 0or a caching sol#tion

    Pattern:

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    66/76

    Pattern:

    e#est Cache

    'et(s try a si%ple cache

    Persist the res#lt 0orever and chec) 0orne" re#ests 0or sa%e reso#rce

     %% Caching wrapper aroun fs#rea'ile./

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    67/76

     var requestCache =  {};

     function cachingReadFile(filename, callback) {

      %%Do we have resource in cache0

      if  (filename in requestCache) { 

    var value =  requestCache7filename8;

       %% 1sync !ehavior: elay result till ne)t tick 

      process.ne&t*ick(function () { callback(null, value); });

      return;

      }

      %% If not, start a new re+uest 

      fs.rea"File(filename, onRead);

     

     %% Cache the result if there is no error 

      function onRead(err, contents) {

      if  (%err) requestCache7filename8 =  contents;  callback(err, contents);

      }

     }

    *ased on ea%ples 0ro%: https:&&gith#$.co%&node$its&distilled

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    68/76

    Usage

     %% *e+uest the (le -,--- times in series

     %% 2ote: for serial re+uests we nee to iterate

     %% with call!acks, rather than within a loop

     var its =  31111; cachingReadFile(file, next);

     

    function next(err, contents) {

      console.log('File contents: ' +  contents);  if  (%(itsAA)) return;

      cachingReadFile(file, next);

     }

    *ased on ea%ples 0ro%: https:&&gith#$.co%&node$its&distilled

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    69/76

    Al%ost /here

     

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    70/76

    var requestBatches =  {}, requestCache =  {};

    function readFile(filename, callback) {

      if  (filename in requestCache) { %% Do we have resource in cache0

      var value =  requestCache7filename8;

       %% Delay result till ne)t tick to act async  process.ne&t*ick(function () { callback(null, value); });

      return;

      }

      if  (filename in requestBatches) { %% Else, oes (le have a !atch0

      requestBatches7filename8.p!sh(callback);

      return;  }

       %% If neither, create new !atch an re+uest 

      var callbacks =  requestBatches7filename8 =  7callback8;

      fs.rea"File(filename, onRead);

       %% Cache the result an "ush !atch

      function onRead(err, file) {  if  (%err) requestCache7filename8 =  file;

      delete requestBatches7filename8;

      for (var i= 1;i2 callbacks.length;i+ + ) { callbacks7i8(err, file); }

      }

    }

    *ased on ea%ples 0ro%: https:&&gith#$.co%&node$its&distilled

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    71/76

    scale0s

    "rote a %od#le 0or scala$le File &-

    https:&&""".np%js.org&pac)age&scale0s 

    Usage:

     var fs =  require(6scaleAfs');

     

    for (var i =  1; i 2  31111; i+ + ) {

      fs.rea"File(filename);

     }

    https://www.npmjs.org/package/scale-fshttps://www.npmjs.org/package/scale-fshttps://www.npmjs.org/package/scale-fshttps://www.npmjs.org/package/scale-fs

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    72/76

    Final /ho#ghts

    Most antipatterns in Node.js co%e 0ro%:

    S)etchy +avaScript heritage• neperience "ith Asynchrono#s /hin)ing

    e%e%$er, let the Event 'oop do theheavy li0ting

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    73/76

     /han)s

    Code sa%ples 0ro% this tal) at:

    https:&&gith#$.co%&cacois&nodepatternsdiscerning

    https://github.com/cacois/node-patterns-discerninghttps://github.com/cacois/node-patterns-discerninghttps://github.com/cacois/node-patterns-discerninghttps://github.com/cacois/node-patterns-discerning

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    74/76

    Disclai%er

     /ho#gh a% an e%ployee o0 theSo0t"are Engineering nstit#te atCarnegie Mellon University, this "o)

    "as not 0#nded $y the SE and doesnot reGect the "or) or opinions o0 theSE or its c#sto%ers.

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    75/76

    'et(s chat

    !aaroncois

    """.codehenge.net

    gith#$.co%&cacois

     /he event loop e@ciently

    Node apps pass asynctas)s to the event

    1 2

  • 8/15/2019 Nodejs Design Patterns 130602183400 Phpapp02

    76/76

    Node.jsEvent

    'oop

    %anages a thread pool andeec#tes tas)s e@cientlyB

     /hread4

     /hread2

     /hreadn

    B /as) 4

     /as) 2

     /as) 3

     /as) 7

    et#rn 4

    Call$ac)4>?

    d t h

    Node.jsapp

    tas)s to the eventloop, along "ith acall$ac)

    >0#nction, call$ac)?

    1 2