Since november 2009 at http://jsconf.com/ europe by Ryan Dahl, because building progress bars into Ruby was just to slow. Written for a data center.
Who is using node
Best tool vs swiss army knife
- Sharding complexity by separating your code
- Composition in favor of inheritance
- Avoid callback hell (http://callbackhell.com/)
- No nested if-then-else, return early
- Error-first callback
- Leverage the ecosystem
- Develop for the clueless stranger
Error-first callbacks
fs.readFile('/foo.txt', function(err, data) {
if(err) {
if(err.fileNotFound) {
return this.sendErrorMessage('File Does not Exist');
}
if(!err.noPermission) {
return next(err);
}
}
console.log(data);
});
Use async
async.parallel({
one: function(callback){
setTimeout(function(){
callback(null, 1);
}, 200);
},
two: function(callback){
setTimeout(function(){
callback(null, 2);
}, 100);
}
},
function(err, results) {
// results is equal to: {one: 1, two: 2}
});
Testing
- There are no points for clever tests
- Test clarity above all else
- Jasmine all in one testing framework
- Mocha follows node standard, no mocks, no asserts
Mocha
describe('yourModuleName', function() {
before(function(){
// The before() callback gets run before all tests in the suite. Do one-time setup here.
});
beforeEach(function(){
// The beforeEach() callback gets run before each test in the suite.
});
it('does x when y', function(){
// Now... Test!
});
after(function() {
// after() is run after all your tests have completed. Do teardown here.
});
});
NodeJs Built-In Assertions
assert.equal(life, 42, 'some message');
assert(life === 3, 'some message');
Chai Assertion Library
foo.should.be.a('string');
expect(foo).to.be.a('string');
assert.typeOf(foo, 'string');
Sinon Spies, Stubs and Mocks
var callback = sinon.stub();
callback.withArgs(42).returns(1);
Mockery Require Mocking
before(function() {
mockery.enable();
mockery.registerAllowable('async');
mockery.registerMock('../some-other-module', stubbedModule);
});
after(function() {
mockery.deregisterAll();
mockery.disable();
});
Rewire Require DI
var rewire = require("rewire");
var myModule = rewire("../lib/myModule.js");
myModule.__set__("path", "/dev/null");
Modules
Type example (preferred)
var privateStaticVariable = true;
module.exports = User;
function User(n) {
this._privateVariable = true;
this.name = n;
}
User.prototype.sayHi = function() {
console.log('Hi, My name is ' + this.name);
};
var User = require('User');
var alice = new User('Alice');
alice.sayHi(); // "Hi, My name is Alice"
Slower, but real private variable (avoid)
module.exports = User;
function User(n) {
var privateVariable = true;
this.publicVariable = n;
this.toggle = function toggle() {
privateVariable = !privateVariable;
}
}
Running multiple node versions
Using EcmaScript 2015 (ES6)