

Agenda
- Why, When and What's Node.js?
- Checking our Javascript
- Node.js Hello World
- What's and how to use NPM
- Dependencies with Common.js
- Callbacks, callbacks and more callbacks
- Express.js to the rescue
- Mongoose and MongoDB
-
Going real time with Socket.io
-
Gulp

Why Node.js
Why, When and What's Node.js


Why Node.js
Why, When and What's Node.js



Why Node.js
Why, When and What's Node.js


Why Node.js
Why, When and What's Node.js

Companies using Node.js




Why Node.js
Why, When and What's Node.js



Why Node.js
Why, When and What's Node.js


Why, When and What's Node.js
Why Node.js

Callback


Blocking I/O
Why Node.js
Why, When and What's Node.js

Why Node.js
Why, When and What's Node.js






How to scale ?

When Node.js
Why, When and What's Node.js


When Node.js
Why, When and What's Node.js


When Node.js
Why, When and What's Node.js



When Node.js
Why, When and What's Node.js


What's Node.js
Why, When and What's Node.js

What's Node.js
Why, When and What's Node.js




NODE.JS SYSTEM ARCHITECTURE
What's Node.js
Why, When and What's Node.js



What's Node.js
Why, When and What's Node.js



What's Node.js: A Hello Node App
Why, When and What's Node.js
// See node-lessons/lesson_0/index.js
var http = require('http');
var PORT = process.env.PORT || 8080;
var HOSTNAME = process.env.HOSTNAME || 'localhost';
var NODE_ENV = process.env.NODE_ENV || 'development';
var counter=0;
var server = http.createServer(function(request, response) {
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('<!DOCTYPE "html">');
response.write('<html>');
response.write('<head>');
response.write('<title>Hello Node Page</title>');
response.write('</head>');
response.write('<body>');
response.write('Hello Node.js ' + counter + ' running as ' + NODE_ENV + '!');
response.write('</body>');
response.write('</html>');
response.end();
console.log('counter: ' + counter + ' request url: ' + request.url);
counter++;
});
server.listen(PORT, HOSTNAME);
console.log('Server is listening at PORT:' + PORT);

What's Node.js: Not just HTTP
Why, When and What's Node.js
// See node-lessons/lesson_0/echo.js
var http = require('net');
var NL = '\r\n';
var RED = '\033[31m';
var YELLOW = '\033[33m';
var GREEN = '\033[32m';
var BLUE = '\033[34m';
var DEFAULT_COLOR = '\033[39m';
var WELCOME = [
NL,
GREEN,
" _/ _/ _/_/_/ _/ " + NL,
" _/_/_/_/_/ _/ _/_/_/ _/_/_/ _/_/_/ " + NL,
" _/ _/ _/_/_/ _/ _/ _/ _/ _/ " + NL,
"_/_/_/_/_/ _/ _/ _/ _/ _/ _/ " + NL,
" _/ _/ _/_/_/ _/_/_/ _/ _/ _/_/_/ " + NL,
NL,
BLUE,
"This is an ",
RED,
"ECHO ",
BLUE,
"service implemented with ",
GREEN,
"NODE.JS",
YELLOW,
NL + NL
]
var server = http.createServer(function (socket) {
socket.write(WELCOME.join(''));
socket.pipe(socket);
});
server.listen(1337, '127.0.0.1');

What are Node.js modules
Why, When and What's Node.js

- 1 to 1 correspondence with 1 file
- Modules are loaded synchronously
- Modules are cached
-
Core modules come with the platform
-
ex: require('http')
-
-
3rd party modules are published as packages to a registry (such as NPM)
-
use:npm install
- installed into node_modules directory
-
-
File modules
- require path starts with '/', './', or '../'
How require(...) works?
Why, When and What's Node.js

If not a core module, and not an explicit path (whether absolute or relative):
- Looks in module's directory for node_modules/
- if not found, continue searching each parent directory until file system root ( / )
- Throw an error (code: MODULE_NOT_FOUND)
How require(...) works?
Why, When and What's Node.js

When requiring a path instead of an explicit file
- Look for package.json ("main" property)
- Look for index.js
EX: require('./my_awesome_lib')
Folder as module
// example content of ./my_awesome_lib/package.json
{ "name" : "my-awesome-library",
"main" : "./implementation/my_lib_impl.js" }
How require(...) works?
Why, When and What's Node.js

Modules can be installed globally using:
- npm install -g [module_name]
But that's just recommended for Command Line Interface (CLI) modules
EX: npm install -g express-generator
If NODE_PATH is set with a single or multiple paths, Node.js will search there. Additionally it will also search in the following paths:
- $HOME/node_modules
- $home/node_library
- #prefix/lib/node
Global modules
No longer considered a good practice but still there for legacy support.
How require(...) works?
Why, When and What's Node.js

More details at:
Some important Javascript concepts
Checking our Javascript
// See javascript-checking/app.js
var assert = function(cond, msg) { console.log((cond?"OK ": "FAIL ") + msg ); }
// Initialization
var port = process.env.PORT || 3000;
var host = process.env.IP || "127.0.0.1";
assert(port=== 3000, "|| operator helps to initialize variables with default values");
// Simple Array [element1, element2, element3, ...]
var mySimpleArray = ["A", 1, function(){return "yes this can be an array element also"}, null, {},port, host, undefined, true];
console.dir(mySimpleArray);
mySimpleArray.push("Let's think the Array also as an stack ;)");
console.dir(mySimpleArray);
mySimpleArray.pop(); // removed las element from stack (LIFO)
console.dir(mySimpleArray);
mySimpleArray.unshift("Let's add an element at the beginning of the array"); // Can you imagine now how to create a FIFO list with this?
console.dir(mySimpleArray);
mySimpleArray.shift('We can also remove it from it\'s first element');
console.dir(mySimpleArray);
assert(mySimpleArray.length === 9, "The Array length is still 9.")
// Associative Array {key1: value1, key2: value2, key3: value3, ...}
// IMPORTANT: Objects are also Associative Arrays ;)
var myAssociativeArray = {
1: "A",
"2": 1,
"showMessage": function(){return "Yes, this can also be an array element"},
_1: null,
'empty':{}, // An empty Object == An empty Associative Array
port: port,
'host': host,
___:undefined,
true: true && false
};
assert(mySimpleArray.length === 9, "The Array length is 9.")
// Functions
function isNimble(){ return true; }
var canFly = function(){ return true; };
var fly = {}; // fly is a reference to an empty object
fly.isDeadly = function(){ return true; };
function yell(n){
return n > 0 ? yell(n-1) + "a" : "hiy";
}
var ninja = function myNinja(){
assert( ninja == myNinja, "This function is named two things - at once!" );
};
console.log(typeof myNinja);
console.log(typeof ninja);
ninja = {
yell: function(n){
return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
},
yell2: function(n){
return n > 0 ? ninja.yell2(n-2) + "a" : "hiy";
}
};
assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." );
assert( ninja.yell2(7) == "hiyaaaa", "A single object isn't too bad, either." );
// Objects
assert(this !== undefined, "Yes we are in the context of a global object so be careful when you reffer to 'this'")
var obj = {};
// How similar are functions to Objects
var fn = function(){};
assert( obj && fn, "Both the object and function exist." );
// Both are Objects and can have properties.
obj.prop = "some value";
fn.prop = new String("some value");
assert( obj.prop == fn.prop, "Both are objects, both have the property." );
assert( obj.prop !== fn.prop
&& typeof fn.prop === "object"
&& typeof obj.prop=== "string", "But they don't refer to the same string base type reference." );
fn.prop = "some value";
assert( typeof fn.prop === typeof obj.prop, "As we are using the same extensive way to define their values now both have the same reference." );
//Function context
var katana = {
isSharp: true,
use: function(){
this.isSharp = !this.isSharp;
}
};
katana.use();
assert( !katana.isSharp, "Verify the value of isSharp has been changed." );
function katanaStatus(){
this.isSharp = true;
}
katanaStatus();
assert( isSharp === true, "A global object now exists with that name and value." );
// Change running context.
var shuriken = {
toss: function(){
this.isSharp = true;
}
};
shuriken.toss();
// How to handle scope
assert( shuriken.isSharp === true, "When it's an object property, the value is set within the object." );
var _ = require('lodash'); //lodash replaces underscore
weaponsBag = {
slots: [
{ type: 'shuriken', subtype: 'NagareManji', efectivity: 60, maxDistance: 15},
{ type: 'shuriken', subtype: 'Manji', efectivity: 50, maxDistance: 20},
{ type: 'shuriken', subtype: 'KoburiRiuManji', efectivity: 45, maxDistance: 12},
{ type: 'shuriken', subtype: 'KotoRyuTeppan', efectivity: 40, maxDistance: 10},
{ type: 'knife', subtype: 'Kunai', efectivity: 70, maxDistance: 5},
{ type: 'knife', subtype: 'Kunai', efectivity: 70, maxDistance: 5},
{ type: 'bomb', subtype: 'SmokeBomb', efectivity: 70, maxDistance: 3, time: 3},
{ type: 'bomb', subtype: 'SmokeBomb', efectivity: 70, maxDistance: 3, time: 3},
{ type: 'dart', subtype: 'PoisonDart', efectivity: 80, maxDistance: 5},
{ type: 'empty'},
],
showBag: function(){
console.dir(this.slots);
},
shurikensRain: function(){
var _this = this;
_.forEach(this.slots, function(weapon, index){
try {
this.slots[index] = { type: 'empty'};
} catch(err){
assert(typeof this.slots === 'undefined', "this.slot is undefined here, err: " + err.message);
};
assert(this!=_this, "Closure to the rescue this!=_this ;)");
if(weapon.type=='shuriken'){
_this.slots[index] = { type: 'empty'};
}
});
},
knivesRain: function(){
_.forEach(this.slots, function(weapon, index){
if(weapon.type=='knife'){
this.slots[index] = { type: 'empty'};
}
}.bind(this));
},
throwBombs: function(){
this.slots = _.map(this.slots, function(weapon) {
return weapon.type=='bomb'?{type:'empty'}:weapon;
});
},
};
weaponsBag.showBag();
weaponsBag.shurikensRain();
weaponsBag.showBag();
weaponsBag.knivesRain();
weaponsBag.showBag();
weaponsBag.throwBombs();
weaponsBag.showBag();
function substract(a, b){
return a - b;
}
assert( substract.call(this, 2, 1) == 1, ".call() takes individual arguments" );
assert( substract.apply(this, [4, 2]) == 2, ".apply() takes an array of arguments" );
// Callbacks
function loop(array, fn){
for ( var i = 0; i < array.length; i++ ) {
// Implement me!
}
}
var num = 0;
loop([0, 1, 2], function(value){
assert(value == num++, "Make sure the contents are as we expect it.");
assert(this instanceof Array, "The context should be the full array.");
});
function SuperNinja(){
this.ninja_name = "Ninja";
}
// Using new
var superNinjaA = SuperNinja();
assert( !superNinjaA, "Is undefined, not an instance of SuperNinja." );
var superNinjaB = new SuperNinja();
assert( superNinjaB.ninja_name === "Ninja", "Property exists on the SuperNinja instance." );
assert( ninja_name === "Ninja", "Property exists on global Object." );
// Working with different instances.
function Samurai(){
this.swung = false;
// Should return true
this.swingSword = function(){
this.swung = !this.swung;
return this.swung;
};
}
var samurai = new Samurai();
assert( samurai.swingSword(), "Calling the instance method." );
assert( samurai.swung, "The samurai has swung the sword." );
var samuraiB = new Samurai();
assert( !samuraiB.swung, "Make sure that the samurai B has not swung his sword." );
// Side effects of not using new
function User(first, last){
if ( !(this instanceof User) )
return new User(first, last);
console.log("calle: " + arguments.callee);
this.name = first + " " + last;
}
var name = "Otero";
var user = User("Leonardo", name);
assert( user, "This was defined correctly, even if it was by mistake." );
assert( name == "Otero", "The right name was maintained." );
// Introspection
function merge(root){
for ( var i = 1; i < arguments.length; i++ )
for ( var key in arguments[i] )
root[key] = arguments[i][key];
return root;
}
var merged = merge({name: "Leonardo"}, {city: "Buenos Aires"});
assert( merged.name == "Leonardo", "The original name is intact." );
assert( merged.city == "Buenos Aires", "And the city has been copied over." );
// Closures
var num = 10;
function addNum(myNum){
return num + myNum;
}
assert( addNum(5) == 15, "Add two numbers together, one from a closure." );
// Public and Private
function BlackNinja(weapon){
this.weapon = weapon;
var slices = 0;
this.getSlices = function(){
return slices;
};
this.slice = function(){
slices++;
};
}
var ninja = new BlackNinja("Katana");
ninja.slice();
assert( ninja.getSlices() == 1, "We're able to access the internal slice data by using a methods." );
assert( ninja.slices === undefined, "But not using private attributes (those defined using var)." );
assert( ninja.weapon === "Katana", "And BTW public data is also accesible to us, we just need to use this." );
// Calling anonymous functions
var add = (function(a, b){ return a + b; })(1,2);
assert( add === 3, "Yes, we can call implicit functions");
// This is an Object and also an Associative Array;
var obj = {a:1, b:2};
// This is a simple Array but also and Object;
var arr = [1,2];
assert(typeof obj === 'object' && obj !== undefined, "Yes obj is of type object");
assert(obj instanceof Object, "It also is an instance of Object");
assert(obj.constructor === Object, "obj constructor is Object");
assert(!(obj instanceof Array), "obj is not an Array");
assert(Array.isArray(arr), "arr is an Array");
assert(typeof arr === 'object' && arr !== undefined, "And yes arr is of type object");
console.log("typeof arr:"+ typeof arr);
assert(arr instanceof Object, "arr also is an instance of Object ;)");
assert(arr instanceof Array, "And it also is an instance of Array ;)");
assert(arr.constructor !== Object, "arr constructor is not Object");
assert(arr.constructor === Array, "arr constructor is Array");
//Initializing a library
var myLib = (function(){
function myLib(){
// Initialize
}
// ...
return myLib;
})();
// Dealing with a broken closure and fixing it
var count = 0;
for ( var i = 0; i < 4; i++ ) {
setTimeout(function(){
assert( i == count++, "Check the value of i." );
}, i * 200);
}
var count2 = 0;
for ( var ii = 0; ii < 4; ii++ ) (function(ii){
setTimeout(function(){
assert( ii == count2++, "Check the value of ii." );
}, ii * 200);
})(ii);
// Using function prototype
function WhiteNinja(){};
WhiteNinja.prototype.swingSword = function(){
return true;
};
var ninjaA = WhiteNinja();
assert( !ninjaA, "Is undefined, not an instance of WhiteNinja." );
var ninjaB = new WhiteNinja();
assert( ninjaB.swingSword(), "Method exists and is callable." );
//Overridding a function prototype
function NinjaStudent(){
this.throwShuriken = function(){
return true;
};
};
// Should return false, but will be overridden
NinjaStudent.prototype.throwShuriken = function(){
return false;
};
var ninja = new NinjaStudent();
assert( ninja.throwShuriken(), "Calling the instance method, not the prototype method." );
// New method definition on already instantiated objects.
function NinjaMaster(){
this.swung = true;
}
var ninjaA = new NinjaMaster();
var ninjaB = new NinjaMaster();
NinjaMaster.prototype.swingSword = function(){
return this.swung;
};
assert( ninjaA.swingSword(), "Method exists, even out of order." );
assert( ninjaB.swingSword(), "and on all instantiated objects." );

Some important Javascript concepts
Checking our Javascript
INITIAL | CONCEPT |
---|---|
S | Single Responsibility Principle (SRP): A function should have only a single responsibility (i.e. only one potential change in the software's specification should be able to affect the specification of the function) |
O | Open/Close Principle (OCP): Software entities should be open for extension, but closed for modification. |
L | Liskov Substitution Principle (LSP): Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program. See also design by contract. |
I | Interface Segregation Principle (ISP):
Many client-specific interfaces are better than one general-purpouse interface. |
D | Dependency Inversion Principle (DIP):
One should depend upon Abstractions. Do not depend upon concretions. |

What's NPM


Installing NPM


Installing NPM packages locally


Installing NPM packages globally


Semantic Versioning and NPM


Creating Node.js modules


"Do one thing well."
"Compose larger units out of smaller, independent units of functionality."
NPM filosofy


Using NPM
# It shows up current NPM installed version
npm --version
# Initialize current folder creating
# a package.json file to store dependencies
npm init
# Shows up NPM configuration like used
# folders
npm config list
# List every globally installed module
npm list --g[lobal]
# List every locally installed module
npm list
# Locally installs express and also adds it
# to package.json
npm install express --save
# Locally installs specific modules but
#just for dev environments
npm install mocha chai --save-dev
# Installs all dependencies declared at
# package.json even dev dependencies
npm install
# Just installs non development
# specific dependencies.
npm install --production
# Locally uninstall a module
npm uninstall express
# Installs a particular module version
npm install underscore@1.8.2
# Updates a module but following what's
# configured at package.json
npm update underscore


More about NPM


THE SIMPLEST MODULE
Dependencies with Common.js
// See node-lessons/lesson_1/hello.js
console.log('Hello World');
// See node-lessons/lesson_1/app.js
require('./hello.js');
>node app.js
Hello World
>

PATTERN 1: DEFINE A GLOBAL
Dependencies with Common.js
// See node-lessons/lesson_2/foo.js
foo = function () {
console.log('foo!');
}
// See node-lessons/lesson_2/foo.js
require('./foo.js');
foo();
>node app.js
foo!
>


PATTERN 2: EXPORT AN ANONYMOUS FUNCTION
Dependencies with Common.js
// See node-lessons/lesson_3/bar.js
module.exports = function () {
console.log('bar!');
}
// See node-lessons/lesson_3/app.js
var bar = require('./bar.js');
bar();
>node app.js
bar!
>

PATTERN 3: EXPORT A NAMED FUNCTION
Dependencies with Common.js
// See node-lessons/lesson_4/fiz.js
exports.fiz = function () {
console.log('fiz!');
}
// See node-lessons/lesson_4/app.js
var fiz = require('./fiz.js').fiz;
fiz();
>node app.js
fiz!
>

PATTERN 4: EXPORT AN ANONYMOUS OBJECT
Dependencies with Common.js
// See node-lessons/lesson_5/buz.js
var Buz = function () {};
Buz.prototype.log = function () {
console.log('buz!');
};
module.exports = new Buz();
// See node-lessons/lesson_5/app.js
var buz = require('./buz.js');
buz.log();
>node app.js
buz!
>

PATTERN 5: EXPORT A NAMED OBJECT
Dependencies with Common.js
// node-lessons/lesson_6/baz.js
var Baz = function () {};
Baz.prototype.log = function () {
console.log('baz!');
};
exports.Baz = new Baz();
// node-lessons/lesson_6/app.js
var baz = require('./baz.js').Baz;
baz.log();
>node app.js
baz!
>

PATTERN 6: EXPORT AN ANONYMOUS PROTOTYPE
Dependencies with Common.js
// See node-lessons/lesson_7/doo.js
var Doo = function () {};
Doo.prototype.log = function () {
console.log('doo!');
}
module.exports = Doo;
// See node-lessons/lesson_7/app.js
var Doo = require('./doo.js');
var doo = new Doo();
doo.log();
>node app.js
doo!
>

PATTERN 7: EXPORT A NAMED PROTOTYPE
Dependencies with Common.js
// See node-lessons/lesson_8/qux.js
var Qux = function () {};
Qux.prototype.log = function () {
console.log('qux!');
};
exports.Qux = Qux;
// See node-course/node-lessons/lesson_8/app.js
var Qux = require('./qux.js').Qux;
var qux = new Qux();
qux.log();
>node app.js
qux!
>

exports VS module.exports
Dependencies with Common.js
module.exports.fiz = "fiz";
exports.buz = "buz";
module.exports === exports;
- exports is a reference to module.exports,
- node automatically creates it as a convenient shortcut.
- For assigning named properties, use either one.

WARNING
Dependencies with Common.js
$ node
> module.exports.qux = "qux";
> exports
{ qux: "qux" }
> exports === module.exports
true
> exports = "wobble wibble wubble!";
> exports === module.exports
false
> exports
"wobble wibble wubble!"
> module.exports
{ qux: "qux" }
// module.exports is canonical
-
Assigning anything to exports directly (instead of exports.something) will overwrite exports reference so exports properties will not be seen from module.exports or available using require.

Callback Hell / Bumeran Code /
Callbacks, callbacks and more callbacks




Callbacks Hell / Bumeran Code
Callbacks, callbacks and more callbacks
// Improving code readability
function x (a) {
do_something(function(){
process(a);
});
}
// can be converted to this:
function x (a) {
do_something(y_maker(a)); // notice we're calling y_maker,
// not passing it in as callback
}
function y_maker (b) {
return function () {
process(b);
};
}


Callbacks
Callbacks, callbacks and more callbacks



Async.js to the rescue
Callbacks, callbacks and more callbacks

Async provides around 70 functions that include the usual 'functional' suspects:
- map
- reduce
- filter
- each
- parallel
- series
- waterfall
As well as some common patterns for asynchronous control flow:

Async.js : series
Callbacks, callbacks and more callbacks

// See node-lessons/lesson_9/async_series.js
var async = require('async');
async.series([
function(callback){
console.log('1st function call starts.');
setTimeout(function(){
console.log('1st function call resolved.');
callback(null, 1); // err, result
}, 1000);
},
function(callback){
console.log('2nd function call starts.');
setTimeout(function(){
console.log('2nd function call resolved.');
callback(null, 2, 3); // err, results
}, 100);
}
],
function(err, results){
// err propagates all errors within the series functions
// results holds all the results, [1, [2, 3]] in this case
console.log('Results return in order as espected ;)');
console.dir(results);
});

Async.js : parallel
Callbacks, callbacks and more callbacks

// See node-lessons/lesson_9/async_parallel.js
var async = require('async');
async.parallel([
function(callback){
console.log('1st function call starts.');
setTimeout(function(){
console.log('1st function call resolved.');
callback(null, 1); // err, result
}, 1000);
},
function(callback){
console.log('2nd function call starts.');
setTimeout(function(){
console.log('2nd function call resolved.');
callback(null, 2); // err, result
}, 100);
}
],
function(err, results){
// err propagates all errors within the parallel functions
// results holds all the results, [1, 2] in this case
console.log('But results return in order as espected ;)');
console.dir(results);
});

Async.js : waterfall
Callbacks, callbacks and more callbacks

// See node-lessons/lesson_9/async_waterfall.js
var async = require('async');
var WINK = ';)';
var SMILEY = ':D';
var TONGUE = ':P';
async.waterfall([
function(callback){
console.log('1st function call starts.');
setTimeout(function(){
console.log('1st function call resolved.');
callback(null, WINK, SMILEY); // err, result, ... cascade params
}, 5000);
},
function(arg1, arg2, callback){
console.log(['2nd function call starts receiving arg1:',
arg1,
'and arg2:',
arg2,
'.'].join(' '));
setTimeout(function(){
console.log('2nd function call resolved.');
var prefix = 'result ';
callback(null,
prefix + TONGUE,
prefix + arg2,
prefix + arg1); // err, ... multiple results is ok
}, 3000);
}
],
function(err, result1, result2, result3){
// err propagates all errors within the waterfall functions
console.log('Important: waterfall can handle multiple results.');
console.dir(result1);
console.dir(result2);
console.dir(result3);
});

More about Async.js?
Callbacks, callbacks and more callbacks


Express.js to the rescue
https://github.com/subfuzion/express-demo


Express.js to the rescue
# Installing Express in our project
npm install express --save
# Do you need a middleware for handling JSON, Raw, Text and URL encoded form data?
npm install body-parser --save
# Do you need a middleware to parse cookies from request headers and populate
# req.cookies with an object keyed by the cookie names?
npm install cookie-parser --save
# Do you need a middleware for handling multipart/form-data?
npm install multer --save
# Do you need session handling using cookie store?
npm install cookie-session --save
# Do you need server logs?
npm install morgan --save
# Do you need to serve static content (i.e. html pages, images, css)?
npm install serve-static --save
# Do you need an authentication library?
npm install passport --save
# Do you want CLI assistance to create your App?
# then globally install express and express-generator
npm install -g express express-generator
Preflight check on

Express.js to the rescue
//server.js
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World');
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
First flight on Express.js

See lesson_10 source code
See lesson_11 source code
Express.js to the rescue
What is Middleware
Middleware pattern is a series of processing units connected together, where the output of one unit is the input for the next one. In Node.js, this often means a series of functions in the form:

function(request, response, next) {
// ... Run some code
next();
};

request -> middleware1 -> middleware2 -> ...middlewareN -> route -> app -> response
Tipical Flow:

Express.js to the rescue
Applying Express middleware

var express = require('express');
var app = express();
//... Define middleware1-N
app.use(middleware1);
app.use(middleware2);
...
app.use(middlewareN);


Express.js to the rescue
Middleware order

var express = require('express');
var logger = require('morgan');
var bodyParser = require('body-parser');
var app = express();
...
app.use(logger('dev'));
app.use(bodyParser.json());

Middlewares are executed in the specified order:

Express.js to the rescue
Two Categories of Express Middleware
- npm modules, e.g., body-parser
- Custom Middleware

See lesson_13 source code for an express-generator example
Express.js to the rescue
Custom Middleware
Creating a Custom Middleware using a reference
Creating a Custom Middleware with anonymous function definition
...
var middleware = function (request, response, next) {
// Modify request or response
// Execute the callback when done
next();
};
...
app.use(middleware);
app.use(function (request, response, next) {
// Modify request or response
// Execute the callback when done
next();
});

Express.js to the rescue
Template Engines
Some examples


Express.js to the rescue
Template Engines
Express.js uses by default
PUG ???... really? ... well ... yes
JADE



Express.js to the rescue
Template Engines: JADE


Express.js to the rescue

Template Engines: JADE/PUG
//-index.jade
doctype html
html(lang="en")
head
title= pageTitle
script(src="/scripts/force.js")
script.
var useTheForce = force.use();
body
h2 These aren't the droids you're looking for
#container.col
p -You can go about your busines.
p -Move along.
May the force be with you and move to node-lessons/lesson_12




















Collection
Document



MongoDB query
Typical SQL query



MongoDB query with projection control


MongoDB insert



MongoDB update



MongoDB remove



MongoDB aggregated query


MongoDB map reduce query


MongoDB documents relationship





var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// create a schema
var userSchema = new Schema({
name: String,
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
admin: Boolean,
location: String,
meta: {
age: Number,
website: String
},
created_at: Date,
updated_at: Date
});
// the schema is useless so far
// we need to create a model using it
var User = mongoose.model('User', userSchema);
// make this available to our users in our Node applications
module.exports = User;
Mongoose

// if our user.js file is at app/models/user.js
var User = require('./app/models/user');
// create a new user called chris
var chris = new User({
name: 'Chris',
username: 'sevilayha',
password: 'password'
});
// call the custom method. this will just add -dude to his name
// user will now be Chris-dude
chris.dudify(function(err, name) {
if (err) throw err;
console.log('Your new name is ' + name);
});
// call the built-in save method to save to the database
chris.save(function(err) {
if (err) throw err;
console.log('User saved successfully!');
});
Mongoose

Mongoose

Ready for a real challenge?
Let's go to node-lessons/lesson_14_earn_your_wings
Socket.io main objective


Socket.io main objective is to enable real time applications on any browser
- Socket between Server & Client
- Send data between clients
- Receive event based data
- Supports almost any browser
- Supports Multiple sockets on a single connection
- Detects disconnection using heartbits
- 100% javascript
- Available on NPM
Socket.io typical usage



Socket.io is real time



Socket.io fallback methods



Socket.io handshake



client socket.io
Node.js server + socket.io
Socket.io handshake



client socket.io
Node.js server + socket.io
transport getway, id and config are returned
Socket.io handshake


client socket.io
Node.js server + socket.io
Heartbeats sent to secure connection healt

client stablish a realtime connection with server
Basic server setup


var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket){
socket.emit('helloworld', { hello: 'world' });
socket.on('other event', function (data) {
console.log(data);
});
});
Basic client setup


<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('other event', { the: 'data' });
});
</script>
Gulp App building



Gulp Life Cycle






Gulp just has 4 main functions

Gulp streams




Gulp streams



Gulp streams



Using Gulp plugins



Using Gulp plugins



Using Gulp plugins



Using Gulp plugins



Running Gulp



Example of Gulpfile.js



Gulp vs Grunt



Gulp vs Grunt






?



Thanks

Node.js FUNdamentals
By Leonardo Daniel Otero
Node.js FUNdamentals
- 3,768