Herramientas de usuario

Herramientas del sitio


wiki2:nodejs:patterns

¡Esta es una revisión vieja del documento!


NodeJS Patterns & good practices

Singleton

//area.js
var PI = Math.PI;

function circle (radius) {  
  return radius * radius * PI;
}

module.exports.circle = circle;  
var areaCalc = require('./area');

console.log(areaCalc.circle(5));  

Observer

// MyFancyObservable.js
var util = require('util');  
var EventEmitter = require('events').EventEmitter;

function MyFancyObservable() {  
  EventEmitter.call(this);
}

util.inherits(MyFancyObservable, EventEmitter);  
MyFancyObservable.prototype.hello = function (name) {  
  this.emit('hello', name);
};
var MyFancyObservable = require('MyFancyObservable');  
var observable = new MyFancyObservable();

observable.on('hello', function (name) {  
  console.log(name);
});

observable.hello('john');  

Factory

function MyClass (options) {  
  this.options = options;
}

function create(options) {  
  // modify the options here if you want
  return new MyClass(options);
}

module.exports.create = create;  

Dependency Injection

function userModel (options) {  
  var db;

  if (!options.db) {
    throw new Error('Options.db is required');
  }

  db = options.db;

  return {
    create: function (done) {
      db.query('INSERT ...', done);
    }
  }
}

module.exports = userModel;  
var db = require('./db');

var userModel = require('User')({  
  db: db
});

Middleware / Pipeline

app.use = function(fn){  
  this.middleware.push(fn);
  return this;
};

So basically when you add a middleware it just gets pushed into a middleware array. So far so good, but what happens when a request hits the server? code> var i = middleware.length; while (i–) {

next = middleware[i].call(this, next);

} </code>

Streams

process.stdin.on('readable', function () {  
    var buf = process.stdin.read(3);
    console.dir(buf);
    process.stdin.read(0);
});
$ (echo abc; sleep 1; echo def; sleep 1; echo ghi) | node consume2.js 
<Buffer 61 62 63>  
<Buffer 0a 64 65>  
<Buffer 66 0a 67>  
<Buffer 68 69 0a> 

Module patterns

Your code uses require to include modules. Modules use exports to make things available.

Named exports - one module, many exported things. Anonymous exports - simpler client interface.

Define a goal

    // foo.js
    foo = function () {
      console.log('foo!');
    }
 

code>

  // app.js
  require('./foo.js');
  foo();

</code>

Export an anonymous function

    // bar.js
    module.exports = function () {
      console.log('bar!');
    }
 
    // app.js
    var bar = require('./bar.js');
    bar();
 

Export a named function

    // fiz.js
    exports.fiz = function () {
      console.log('fiz!');
    }
 
    // app.js
    var fiz = require('./fiz.js').fiz;
    fiz();
 

Export an anonymous object

    // buz.js
    var Buz = function () {};

    Buz.prototype.log = function () {
      console.log('buz!');
    };

    module.exports = new Buz();
 
    // app.js
    var buz = require('./buz.js');
    buz.log();

Export a named object

    // baz.js
    var Baz = function () {};

    Baz.prototype.log = function () {
      console.log('baz!');
    };

    exports.Baz = new Baz();
 
 
    // app.js
    var baz = require('./baz.js').Baz;
    baz.log();
 

Export an anonymous prototype

    // doo.js
    var Doo = function () {};

    Doo.prototype.log = function () {
        console.log('doo!');
    }

    module.exports = Doo;
 
    // app.js
    var Doo = require('./doo.js');
    var doo = new Doo();
    doo.log();
 

Export a named prototype

// qux.js
    var Qux = function () {};

    Qux.prototype.log = function () {
      console.log('baz!');
    };

    exports.Qux = Qux;
 
 
    // app.js
    var Qux = require('./qux.js').Qux;
    var qux = new Qux();
    qux.log();

Callback convention

Modules should expose an error-first callback interface.

The next example checks, if an Error happened during the execution. You should always check for them.

function readJSON(filePath, callback) {  
  fs.readFile(filePath, function(err, data) {
    var parsedJson;

    // Handle error
    if (err) {
       return callback(err);
    }

    // Parse JSON
    try {
      parsedJson = JSON.parse(data);
    } catch (exception) {
      return callback(exception);
    }

    // Everything is ok
    return callback(null, parsedJson);
  });
}

Some good practices

Try to avoid this and new. Node involves passing around lots of callbacks, and heavy use of higher-level functions to manage control flow. Using a functional style will save you a lot of trouble. Of course, there are some cases, when prototypes can be more efficient, but if possible, try to avoid them.

Start a new project with npm init. The init command helps you create the application's package.json file. It sets some defaults, which can be later modified. Start writing your fancy new application should begin with:

mkdir my-awesome-new-project  
cd my-awesome-new-project  
npm init  

Specify a start and test script. In your package.json file you can set scripts under the scripts section. By default, npm init generates two, start and test. These can be run with npm start and npm test. Also, as a bonus point: you can define custom scripts here and can be invoked with npm run-script <SCRIPT_NAME>. Note, that NPM will set up $PATH to look in node_modules/.bin for executables. This helps avoid global installs of NPM modules.

Production/staging deployments should be done with environment variables. The most common way to do this is to set the NODE_ENV variable to either production or staging. Depending on your environment variable, you can load your configuration, with modules like nconf. Of course, you can use other environment variables in your Node.js applications with process.env, which is an object that contains the user environment.

wiki2/nodejs/patterns.1494533141.txt.gz · Última modificación: 2020/05/09 09:24 (editor externo)