Node.js® is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven , non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.
Source: Node.js
Ryan Dahl
Creator of Node.js
Source: Node.js - Wikipedia
Source: Node.js Wiki & Node.js Pass Hosting Providers
Download Link: https://nodejs.org/download/
console.log('Hello world!');
$ node hello.js
Hello world!
Source: Node.js Modules
// FILENAME: mymodule.js
// following assignment can be simplified as
// `exports.sum = ...`
module.exports.sum = function(a, b) {
return a + b;
};
// FILENAME: test.js
// load mymodule.js
var mymod = require('./mymodule');
// call sum method
console.log(mymod.sum(1, 2));
Source: Node.js API
// load file system module
var fs = require('fs');
// read file through sync API
var buf = fs.readFileSync('test.txt');
// read file through async API
fs.readFile('test.txt', function(err, buf) {
// when failed, err will be assigned to Error object.
});
Many objects in Node emit events. For example,
EventEmitter API
Source: Node.js Events API
// FILENAME: events-demo.js
var util = require("util");
var events = require('events');
// write your own class
var MyClass = function() {
// invoke super class constructor
events.EventEmitter.call(this);
};
// inherit from `events.EventEmitter`
util.inherits(MyClass, events.EventEmitter);
var myobj = new MyClass();
// attach event handler with `EventEmitter.on()`
myobj.on('myEvent', function(msg1, msg2, msg3) {
console.log(msg1, msg2, msg3);
});
// emit "myEvent" with message
myobj.emit('myEvent', '1st', '2nd', '3rd');
Source: process.nextTick
// FILENAME: timers.js
setTimeout(function() {
console.log('setTimeout(0)');
}, 0);
setInterval(function() {
console.log('setInterval(1s)');
}, 1000);
process.nextTick(function() {
console.log('nextTick');
});
$ node timers.js
nextTick
setTimeout(0)
setInterval(1s)
setInterval(1s)
setInterval(1s)
setInterval(1s)
setInterval(1s)
Pure JavaScript is Unicode friendly but not nice to binary data. When dealing with TCP streams or the file system, it's necessary to handle octet streams. Node has several strategies for manipulating, creating, and consuming octet streams.
Raw data is stored in instances of the Buffer class. A Buffer is similar to an array of integers but corresponds to a raw memory allocation outside the V8 heap. A Buffer cannot be resized.
Converting between Buffers and JavaScript string objects requires an explicit encoding method. 'utf8' is an encoding for multibyte encoded Unicode characters. Many web pages and other document formats use UTF-8.
Source: Node.js Buffer
A stream is an abstract interface implemented by various objects in Node.
Source: Node.js Streams
Source: Nodejs.org
// FILENAME: http-server.js
// load http module
var http = require('http');
// create an HTTP server
var server = http.createServer();
// attach the handler to 'request' event of server
server.on('request', function (req, res) {
// write Content-Type header to the response with status code 200 - OK
res.writeHead(200, {'Content-Type': 'text/plain'});
// `res.end` write to the response and close the response stream
res.end('Hello World\n');
});
// bind the server and it will block the exiting
server.listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
$ node ./http-server.js
Server running at http://127.0.0.1:1337/
Launch server with Node.js
Access the server by browser with http://localhost:1337/
Source: about npm
Source: npm package.json
{
"name": "my-pkg",
"versoin": "1.0.1",
"main": "main.js",
"description": "This is my first npm package :)",
"dependencies": {
"ws": "0.7.2"
}
}
Source: npm package.json
Creating a user
Publishing the package
Source: Publishing NPM Modules
Updating the package
Source: Publishing NPM Modules
Sync API | Async API | |
---|---|---|
Block Event Loop | Yes | No |
Return Value | Return immediately after function call | Return with callback function |
Performance | Low | High |
Programing | Easy | Hard |
Usage Scenario | Shell / client script | Server side script |
Always use async API on server side scripting
Always check errors first in async callback
// FILENAME: async-api.js
var fs = require('fs');
// 1. use async API
fs.raedFile('some/file', function(err, buf) {
// 2. process error
if (processError(err)) return;
// put your logic here
});
function processError(err) {
if (err) {
console.error(err);
return true;
} else {
return false;
}
}
// FILENAME: nested-callback.js
var fs = require('fs');
fs.readdir('some/dir', function(err, files) {
// LEVEL - 1
// process err
if (processError(err)) {
return;
}
files.forEach(function(file) {
fs.stat('some/dir/' + file, function(err, stats) {
// LEVEL - 2
// process err
if (processError(err)) {
return;
}
if (stats.isFile()) {
fs.readFile('some/dir/' + file, function(err, buf) {
// LEVEL - 3
if (processError(err)) {
return;
}
// dare you put more nested callback here?
}); // fs.readFile
}
}); // fs.stat
}); // files.forEach
}); // fs.readdir
// FILENAME: async-bkm1.js
var fs = require('fs');
// 1. use async API
fs.readdir('some/dir', function(err, files) {
// 2. process error
if (processError(err)) return;
// 3. avoid too much nested callbacks ...
files.forEach(function(file) {
statFile(file);
});
});
// 3. ... and do another async call in a separate function
function statFile(file) {
fs.statFile('some/dir/' + file, function(err, stats) {
// 2. process error
if (processError(err)) return;
if (stats.isFile()) readFile(file);
});
}
// 3. ... and do another async call in a separate function
function readFile(file) {
fs.readFile('some/dir/' + file, function(err, buf) {
// process error
// and put your logic below
});
}
by refactoring into separate functions
Source: Promise
A Promise represents a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers to an asynchronous action's eventual success value or failure reason.
This lets asynchronous methods return values like synchronous methods: instead of the final value, the asynchronous method returns a promise of having a value at some point in the future.
Promise is a standard object since of ES6.
Source: Promise
A Promise is in one of these states:
Source:
Source: Promise
Source: Promise
// FILENAME: promise-simple.js
console.log('before promise');
new Promise(function(resolve, reject) {
resolve(1234);
}) // p1
.then(function(val) { // onResolve
console.log('p1 resolved with ' + val);
}, function(err) { // onReject
console.error('you should not see this because ' +
'no ops rejected previously');
}); // p2
console.log('after promise');
$ node promise.js
before promise
after promise
p1 resolved with 1234
// FILENAME: promise.js
new Promise(function(resolve, reject) {
// delay 2 seconds
setTimeout(function() {
// ... then resolve with 1234
resolve(1234);
}, 2000);
}) // p1
.then(function(val) {
console.log('p1 resolved with ' + val);
// return a bare value "abcd"
return 'abcd';
}) // p2
.then(function(val) {
console.log('p2 resolved with ' + val);
// return a thenable in rejected state
return Promise.reject('bad things happens in p3');
}) // p3
.then(function(val) {
console.log('you should not see this because ' +
'previous ops rejected');
}) // p4
.catch(function(reason) { // onReject
// error happens
console.error('rejected with reason: '
+ reason);
// explicitly return a thenable in resolved state
return Promise.resolve(Math.random());
}) // p5
.then(function(val) {
console.log('p5 resolved with ' + val);
}, function(err) { // onReject
console.error('you should not see this because ' +
'no ops rejected previously');
}); // p6
$ node promise.js
p1 resolved with 1234
p2 resolved with abcd
rejected with reason: bad things happens in p3
p5 resolved with 0.0031185115221887827
// FILENAME: async-callback.js
function async(value, callback) {
// do some stuff
// if fail, invoke callback with
// the error
var err = hasError();
if (err) {
callback(err);
}
// and if success, invoke callback
// with result
callback(null, result);
}
// FILENAME: async-promise.js
// 1. No need to pass callback as argument
function async(value) {
// 2. return the promise object
return new Promise(function(resolve,
reject) {
// do some stuff
// 3. if fail, invoke reject with
// the error
var err = hasError();
if (err) {
reject(err);
}
// 4. and if success, invoke resolve
// with the result
resolve(result);
});
}
// FILENAME: async-nested-callback.js
// async1, async2, async3 invoke callback
// when it's done
async1(function(err, value1) {
if (processError(err)) return;
async2(value1, function(err, value2) {
if (processError(err)) return;
async3(value2, function(err, value3) {
if (processError(err)) return;
// ...
});
});
});
// FILENAME: async-with-promise.js
// async1, async2, async3 returns a resolved
// Promise on success or a rejected Promise
// on failure
async1()
.then(function(value1){
return async2(value1);
})
.then(function(value2){
return async3(value2);
})
.then(function() {
// ...
})
.catch(processError);
Nested callbacks
Chainable callbacks
Final Version
// FILENAME: async-with-promise-final.js
// async1, async2, async3 returns a resolved
// Promise on success or a rejected Promise
// on failure
async1()
.then(async2)
.then(async3)
.then(function() {
// ...
})
.catch(processError);
A tool for creating and composing asynchronous promises in JavaScript. -- by Kris Kowal
The Q module can be loaded as:
Q provides helper functions to wrap async Node.js APIs into promise-styled API
Source: Q API Reference
var fs = require('fs');
var Q = require('q');
// wrap and invoke `fs.readFile` to make it
// return a promise
Q.nfapply(fs.readFile, ['some.txt', 'utf-8'])
.then(function(txt) {
console.log(txt);
}, function(err) {
console.error(err);
});