KEMBAR78
Node.js in action | PDF
Node.js in Action
Simon Su @ MiCloud
Objective
● Node.js Installation
● Node.js Basic
● Node.js Web Framework - Express
Install Node.js
● Download source code
● Install
tar -zxf node-vx.x.x.tar.gz
cd node-vx.x.x
./configure
./configure --prefix=/opt/node
make
sudo make install
Node.js install - Install from Source
● Mac安裝Node.js:
○ Mac版本安裝程式為node-vx.x.x.pkg,執行pkg安裝程式後,將會有安裝
程序帶領您安裝完Node.js
○ 其他安裝支援:MacPort, homebrew
● SmartOS安裝Node.js:
○ pkgin search node
○ pkgin install nodejs-0.4.9
● Windows安裝Node.js:
○ v0.6.x前安裝Node.js於Windows上必須先行安裝 cygwin 然後採用
source install方式安裝
○ v0.6.x後提供msi安裝檔案
Node.js install - All OS
Node.js install - v0.6.8+ support
Node.js vs Javascript
Node.js vs Javascript
Node.js
● Server side language
JavaScript
● Client side language
Node.js Basic
Node.js Read-Eval-Print-Loop (REPL)
$ node
> var os=require('os');
undefined
> os.hostname()
'SimonAIR.local'
>
undefined
>
(^C again to quit)
>
$
指令列直接執行node
鍵入測試指令
使用Ctri + C (兩次) 離開
Basic of Node - 基本語法
● 載入模組
var http = require('http');
● 分享模組
export
module.export
● 註解
// This is a common
/* This is a common */
● 變數
name = value //global
var name = value
● 執行
node nodejs-file-name.js
● 全域物件(Global Objects)
● global
● process
● console
● Buffer
● require()
● require.resolve()
● require.cache
● __filename
● __dirname
● module
● exports
● setTimeout(cb, ms)
● clearTimeout(t)
● setInterval(cb, ms)
● clearInterval(t)
Basic of Node - Exception
$ node 003-for3.js
/Users/jellychang/Workspaces/NodeWS/Sample/003-for3.js:1
process.argv ){
^
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
SyntaxError: Unexpected token )
at Module._compile (module.js:427:25)
at Object..js (module.js:450:10)
at Module.load (module.js:351:31)
at Function._load (module.js:310:12)
at Array.0 (module.js:470:10)
at EventEmitter._tickCallback (node.js:192:40)
錯誤程式區段與位置資訊
Stack trace
Stack trace DETAIL
錯誤原因
Basic of Node - Language Core
● 順序 (Sequence)
● 判斷 (If ... Then .... Else ....)
● 迴圈 (Loops)
Basic of Node -
Non-Block vs Sequence
$ cat 000-sequence.js
console.log('The start of node...');
for(i = 0; i< 3 ; i++ ){
console.log('=>' + i);
}
console.log('The end of node...');
$ node 000-sequence.js
The start of node...
=>0
=>1
=>2
The end of node...
#cat 000-nonblock2.js
setTimeout(function(){
console.log("bar...");
}, 1000);
console.log("foo...");
$ node 000-unblock2.js
foo... (will wait...)
bar...
Basic of Node - if condition
if (CONDITION) {
RULE
} else if {
RULE
} else {
RULE
}
#!/usr/bin/env node
//003-if.js
if ( process.argv[2] == 1 ) {
console.log('input 1...');
} else if (process.argv[2] == 2) {
console.log('input 2...');
} else {
console.log('not 1 or 2...');
}
$ ./003-if.js
not 1 or 2...
$ ./003-if.js 1
input 1...
$ ./003-if.js 2
input 2...
Basic of Node - switch
switch ( EVENT ) {
case EVENT_VALUE:
PROCESS
break;
... (other case)
default:
PROCESS
break;
}
#003-switch.js
console.log('-->' + process.argv[2]);
switch ( process.argv[2] ) {
case '1':
console.log('==>1');
break;
case '10':
console.log('==>10');
break;
default:
console.log('default...');
break;
}
$ node 003-switch.js 1
-->1
==>1
Basic of Node - for loop
for ( i in SET ) {
PROCESS...
}
#003-for.js
for ( i in process.argv ){
console.log('-->' + i +
'=' + process.argv[i]);
}
$ node 003-for.js 1 2 3
-->0=node
-->1=/.../Sample/003-for.js
-->2=1
-->3=2
-->4=3
Basic of Node - for loop
for ( KEY=VALUE;
BREAK_CONDITION;
BREAK_RULE) {
PROCESS
}
#003-for2.js
for ( i=0 ; i < 5 ; i++ ){
console.log(i);
}
$ node 003-for2.js
0
1
2
3
4
Basic of Node - while loop
while ( CONDITION ){
PROCESS
[BREAK_RULE]
}
$ cat 003-while.js
i = 5;
while(i < process.argv[2]){
console.log('-->' + i);
i++;
}
$ node 003-while.js 10
-->5
-->6
-->7
-->8
-->9
Node Ecosystem - NPM
Node Package Management
Install NPM
● >= Node.js 0.6.*
○ Congratulation, in already included in the Node.js
● < Node.js 0.6.*
● One Line Install
curl http://npmjs.org/install.sh | sh
● More Than One Line Install
○ Get the code... https://github.com/isaacs/npm
○ Make & Make install it...
● Windows Install
○ Download a zip file from http://npmjs.org/dist/
○ Unpack it in the same folder where node.exe
lives
NPM Basic Usage
Search:
npm search [some search terms ...]
ex: npm search express
Install:
npm install <name>
ex: npm install express
● Remove:
npm uninstall <name>[@<version> [<name>[@<version>]...]
ex: npm uninstall express
NPM advance commands
● npm list
List the detail help contents
● npm install <pkg. name> -gd
Install the package into global folder.
○ Basicly, the npm install <pkg. name> will install the
package into the user home directory, like:
$HOME/node_modules/*
○ Npm related information will store in $HOME/.npm
Best NPM packages
● View module: jade, express, ejs
● MySQL connector: mysql
● Mailer: nodemailer
● NoSQL: felix-couchdb, mongodb
Node.js Web Fraework -
Express / Ejs
Basic Web Server
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello Worldn');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
3Steps using express/ejs framework
1. Install express, ejs, jade
npm install express ejs jade -gd
PS: Install specific version of module
npm install express@2.5.9 [-gd]
2. Create your project
express <your project name>
ex: express TestPrj
3. Sync project module
cd <your project name> && npm install
ex: cd TestPrj && npm install
Testing of Created Project
# cd $YOUR_WORKSPACE/TestPrj
# node app.js
# cd $YOUR_WORKSPACE/TestPrj
# ls -ltr
總計 24
drwxr-xr-x 5 root root 316 2012-03-30 00:41 public
drwxr-xr-x 2 root root 182 2012-03-30 00:41 routes
drwxr-xr-x 2 root root 252 2012-03-30 00:41 views
-rw-r--r-- 1 root root 153 2012-03-30 00:41 package.json
-rw-r--r-- 1 root root 783 2012-03-30 00:41 app.js
drwxr-xr-x 5 root root 303 2012-03-30 00:41 node_modules
# node app.js
Express server listening on port 3000 in development mode
Using ejs as View Engine - Config
//file: app.js
//Configure route setting
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.bodyParser());
app.use(express.cookieParser());
//app.use(express.session({ secret: "keyboard cat" }));
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
app.set("view options", {layout : true});
});
//Configure routing
app.get('/', function(req, res){
res.render('index', {
title: 'Express'
});
});
var express = require('express')
, routes = require('./routes');
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions:
true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.get('/', routes.index);
app.listen(3000, function(){
console.log("Express server listening on port %d in
%s mode", app.address().port, app.settings.env);
});
Using ejs as View Engine - layout
/* file: /view/layout.ejs */
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<!-- /page -->
<div data-role="page">
<!-- /header -->
<div data-role="header">
<h1>My Title</h1>
</div>
<!-- /content -->
<%- body %>
</div>
</body>
</html>
!!!
html
head
title= title
link(rel='stylesheet',
href='/stylesheets/style.css')
body
block content
Using ejs as View Engine - View
/* file: /view/index.ejs */
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
extends layout
block content
h1= title
p Welcome to #{title}
Configure REST routing
// file: app.js
app.get('/getUsedExam/:classid', refEngin.getUsedExam);
app.get('/getUsedExam/:classid/:teacherid', refEngin.getUsedExam);
app.get('/getUsedExam/:classid/:teacherid/:examid', refEngin.getUsedExam);
// file: routes/someRouter.js
exports.getUserdExam = function(req, res, next) {
var classid = req.params.classid;
...(skip)
console.log('classid: ' + classid );
res.render('simeViewEjsFile', {result: classid});
});
};
Node.js MySQL
Connector
Installing MySQL connector
$ npm install mysql
npm http GET https://registry.npmjs.org/mysql
npm http 304 https://registry.npmjs.org/mysql
npm http GET https://registry.npmjs.org/hashish/0.0.4
npm http 304 https://registry.npmjs.org/hashish/0.0.4
npm http GET https://registry.npmjs.org/traverse
npm http 304 https://registry.npmjs.org/traverse
mysql@0.9.5 ./node_modules/mysql
└── hashish@0.0.4
Using MySQL connector - Config
$ vi mysql-config.js
var db_options = {
host: 'your.database.address',
port: your_database_port,
user: 'access_database_name',
password: 'access_database_password',
database: 'database_that_will_be_use'
};
var mysql = new require('mysql'), db = null;
if(mysql.createClient) {
db = mysql.createClient(db_options);
} else {
db = new mysql.Client(db_options);
db.connect(function(err) {
if(err) {
console.error('connect db ' + db.host + ' error: ' + err);
process.exit();
}
});
}
exports.db = db;
/* file: routes/someRoute.js */
var config = require('./mysql-config')
, db = config.db;
exports.checkExamStatus = function(req, res, next) {
var sql = 'select * from some_talbe a where a.some_column = ? and a.some_column2 = ?';
var some_condition = req.params.some_condition;
var cond = [some_condition, some_condition2];
console.log('Query: ' + sql );
console.log('Cond: ' + cond);
db.query(sql, cond, function(err, rows, fiels) {
if(err) return next(err);
res.render('simpleJsonResult', {result: rows});
});
};
/* file: view/simpleJsonResult.ejs */
<%-JSON.stringify(result)%>
Using MySQL connector - Query
/* file: routes/someRoute.js */
var config = require('./mysql-config')
, db = config.db;
exports.checkExamStatus = function(req, res, next) {
var sql = 'select * from some_talbe a where 1=1 ';
var some_condition = req.params.some_condition;
var cond = new Array();
if (req.params.some_condition != null) {
sql += ' and a.some_column = ? ';
cond.push(some_condition);
}
console.log('Query: ' + sql );
console.log('Cond: ' + cond);
db.query(sql, cond, function(err, rows, fiels) {
if(err) return next(err);
res.render('simpleJsonResult', {result: rows});
});
};
Using MySQL connector - Query 2
Enjoy Your Node
END

Node.js in action

  • 1.
  • 2.
    Objective ● Node.js Installation ●Node.js Basic ● Node.js Web Framework - Express
  • 3.
  • 4.
    ● Download sourcecode ● Install tar -zxf node-vx.x.x.tar.gz cd node-vx.x.x ./configure ./configure --prefix=/opt/node make sudo make install Node.js install - Install from Source
  • 5.
    ● Mac安裝Node.js: ○ Mac版本安裝程式為node-vx.x.x.pkg,執行pkg安裝程式後,將會有安裝 程序帶領您安裝完Node.js ○其他安裝支援:MacPort, homebrew ● SmartOS安裝Node.js: ○ pkgin search node ○ pkgin install nodejs-0.4.9 ● Windows安裝Node.js: ○ v0.6.x前安裝Node.js於Windows上必須先行安裝 cygwin 然後採用 source install方式安裝 ○ v0.6.x後提供msi安裝檔案 Node.js install - All OS
  • 6.
    Node.js install -v0.6.8+ support
  • 7.
  • 8.
    Node.js vs Javascript Node.js ●Server side language JavaScript ● Client side language
  • 9.
  • 10.
    Node.js Read-Eval-Print-Loop (REPL) $node > var os=require('os'); undefined > os.hostname() 'SimonAIR.local' > undefined > (^C again to quit) > $ 指令列直接執行node 鍵入測試指令 使用Ctri + C (兩次) 離開
  • 11.
    Basic of Node- 基本語法 ● 載入模組 var http = require('http'); ● 分享模組 export module.export ● 註解 // This is a common /* This is a common */ ● 變數 name = value //global var name = value ● 執行 node nodejs-file-name.js ● 全域物件(Global Objects) ● global ● process ● console ● Buffer ● require() ● require.resolve() ● require.cache ● __filename ● __dirname ● module ● exports ● setTimeout(cb, ms) ● clearTimeout(t) ● setInterval(cb, ms) ● clearInterval(t)
  • 12.
    Basic of Node- Exception $ node 003-for3.js /Users/jellychang/Workspaces/NodeWS/Sample/003-for3.js:1 process.argv ){ ^ node.js:201 throw e; // process.nextTick error, or 'error' event on first tick ^ SyntaxError: Unexpected token ) at Module._compile (module.js:427:25) at Object..js (module.js:450:10) at Module.load (module.js:351:31) at Function._load (module.js:310:12) at Array.0 (module.js:470:10) at EventEmitter._tickCallback (node.js:192:40) 錯誤程式區段與位置資訊 Stack trace Stack trace DETAIL 錯誤原因
  • 13.
    Basic of Node- Language Core ● 順序 (Sequence) ● 判斷 (If ... Then .... Else ....) ● 迴圈 (Loops)
  • 14.
    Basic of Node- Non-Block vs Sequence $ cat 000-sequence.js console.log('The start of node...'); for(i = 0; i< 3 ; i++ ){ console.log('=>' + i); } console.log('The end of node...'); $ node 000-sequence.js The start of node... =>0 =>1 =>2 The end of node... #cat 000-nonblock2.js setTimeout(function(){ console.log("bar..."); }, 1000); console.log("foo..."); $ node 000-unblock2.js foo... (will wait...) bar...
  • 15.
    Basic of Node- if condition if (CONDITION) { RULE } else if { RULE } else { RULE } #!/usr/bin/env node //003-if.js if ( process.argv[2] == 1 ) { console.log('input 1...'); } else if (process.argv[2] == 2) { console.log('input 2...'); } else { console.log('not 1 or 2...'); } $ ./003-if.js not 1 or 2... $ ./003-if.js 1 input 1... $ ./003-if.js 2 input 2...
  • 16.
    Basic of Node- switch switch ( EVENT ) { case EVENT_VALUE: PROCESS break; ... (other case) default: PROCESS break; } #003-switch.js console.log('-->' + process.argv[2]); switch ( process.argv[2] ) { case '1': console.log('==>1'); break; case '10': console.log('==>10'); break; default: console.log('default...'); break; } $ node 003-switch.js 1 -->1 ==>1
  • 17.
    Basic of Node- for loop for ( i in SET ) { PROCESS... } #003-for.js for ( i in process.argv ){ console.log('-->' + i + '=' + process.argv[i]); } $ node 003-for.js 1 2 3 -->0=node -->1=/.../Sample/003-for.js -->2=1 -->3=2 -->4=3
  • 18.
    Basic of Node- for loop for ( KEY=VALUE; BREAK_CONDITION; BREAK_RULE) { PROCESS } #003-for2.js for ( i=0 ; i < 5 ; i++ ){ console.log(i); } $ node 003-for2.js 0 1 2 3 4
  • 19.
    Basic of Node- while loop while ( CONDITION ){ PROCESS [BREAK_RULE] } $ cat 003-while.js i = 5; while(i < process.argv[2]){ console.log('-->' + i); i++; } $ node 003-while.js 10 -->5 -->6 -->7 -->8 -->9
  • 20.
    Node Ecosystem -NPM Node Package Management
  • 21.
    Install NPM ● >=Node.js 0.6.* ○ Congratulation, in already included in the Node.js ● < Node.js 0.6.* ● One Line Install curl http://npmjs.org/install.sh | sh ● More Than One Line Install ○ Get the code... https://github.com/isaacs/npm ○ Make & Make install it... ● Windows Install ○ Download a zip file from http://npmjs.org/dist/ ○ Unpack it in the same folder where node.exe lives
  • 22.
    NPM Basic Usage Search: npmsearch [some search terms ...] ex: npm search express Install: npm install <name> ex: npm install express ● Remove: npm uninstall <name>[@<version> [<name>[@<version>]...] ex: npm uninstall express
  • 23.
    NPM advance commands ●npm list List the detail help contents ● npm install <pkg. name> -gd Install the package into global folder. ○ Basicly, the npm install <pkg. name> will install the package into the user home directory, like: $HOME/node_modules/* ○ Npm related information will store in $HOME/.npm
  • 24.
    Best NPM packages ●View module: jade, express, ejs ● MySQL connector: mysql ● Mailer: nodemailer ● NoSQL: felix-couchdb, mongodb
  • 25.
    Node.js Web Fraework- Express / Ejs
  • 26.
    Basic Web Server varhttp = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello Worldn'); }).listen(1337, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1337/');
  • 27.
    3Steps using express/ejsframework 1. Install express, ejs, jade npm install express ejs jade -gd PS: Install specific version of module npm install express@2.5.9 [-gd] 2. Create your project express <your project name> ex: express TestPrj 3. Sync project module cd <your project name> && npm install ex: cd TestPrj && npm install
  • 28.
    Testing of CreatedProject # cd $YOUR_WORKSPACE/TestPrj # node app.js # cd $YOUR_WORKSPACE/TestPrj # ls -ltr 總計 24 drwxr-xr-x 5 root root 316 2012-03-30 00:41 public drwxr-xr-x 2 root root 182 2012-03-30 00:41 routes drwxr-xr-x 2 root root 252 2012-03-30 00:41 views -rw-r--r-- 1 root root 153 2012-03-30 00:41 package.json -rw-r--r-- 1 root root 783 2012-03-30 00:41 app.js drwxr-xr-x 5 root root 303 2012-03-30 00:41 node_modules # node app.js Express server listening on port 3000 in development mode
  • 29.
    Using ejs asView Engine - Config //file: app.js //Configure route setting app.configure(function(){ app.set('views', __dirname + '/views'); app.set('view engine', 'ejs'); app.use(express.bodyParser()); app.use(express.cookieParser()); //app.use(express.session({ secret: "keyboard cat" })); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(__dirname + '/public')); app.set("view options", {layout : true}); }); //Configure routing app.get('/', function(req, res){ res.render('index', { title: 'Express' }); }); var express = require('express') , routes = require('./routes'); var app = module.exports = express.createServer(); // Configuration app.configure(function(){ app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(__dirname + '/public')); }); app.configure('development', function(){ app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.configure('production', function(){ app.use(express.errorHandler()); }); // Routes app.get('/', routes.index); app.listen(3000, function(){ console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env); });
  • 30.
    Using ejs asView Engine - layout /* file: /view/layout.ejs */ <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <title><%= title %></title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <!-- /page --> <div data-role="page"> <!-- /header --> <div data-role="header"> <h1>My Title</h1> </div> <!-- /content --> <%- body %> </div> </body> </html> !!! html head title= title link(rel='stylesheet', href='/stylesheets/style.css') body block content
  • 31.
    Using ejs asView Engine - View /* file: /view/index.ejs */ <h1><%= title %></h1> <p>Welcome to <%= title %></p> extends layout block content h1= title p Welcome to #{title}
  • 32.
    Configure REST routing //file: app.js app.get('/getUsedExam/:classid', refEngin.getUsedExam); app.get('/getUsedExam/:classid/:teacherid', refEngin.getUsedExam); app.get('/getUsedExam/:classid/:teacherid/:examid', refEngin.getUsedExam); // file: routes/someRouter.js exports.getUserdExam = function(req, res, next) { var classid = req.params.classid; ...(skip) console.log('classid: ' + classid ); res.render('simeViewEjsFile', {result: classid}); }); };
  • 33.
  • 34.
    Installing MySQL connector $npm install mysql npm http GET https://registry.npmjs.org/mysql npm http 304 https://registry.npmjs.org/mysql npm http GET https://registry.npmjs.org/hashish/0.0.4 npm http 304 https://registry.npmjs.org/hashish/0.0.4 npm http GET https://registry.npmjs.org/traverse npm http 304 https://registry.npmjs.org/traverse mysql@0.9.5 ./node_modules/mysql └── hashish@0.0.4
  • 35.
    Using MySQL connector- Config $ vi mysql-config.js var db_options = { host: 'your.database.address', port: your_database_port, user: 'access_database_name', password: 'access_database_password', database: 'database_that_will_be_use' }; var mysql = new require('mysql'), db = null; if(mysql.createClient) { db = mysql.createClient(db_options); } else { db = new mysql.Client(db_options); db.connect(function(err) { if(err) { console.error('connect db ' + db.host + ' error: ' + err); process.exit(); } }); } exports.db = db;
  • 36.
    /* file: routes/someRoute.js*/ var config = require('./mysql-config') , db = config.db; exports.checkExamStatus = function(req, res, next) { var sql = 'select * from some_talbe a where a.some_column = ? and a.some_column2 = ?'; var some_condition = req.params.some_condition; var cond = [some_condition, some_condition2]; console.log('Query: ' + sql ); console.log('Cond: ' + cond); db.query(sql, cond, function(err, rows, fiels) { if(err) return next(err); res.render('simpleJsonResult', {result: rows}); }); }; /* file: view/simpleJsonResult.ejs */ <%-JSON.stringify(result)%> Using MySQL connector - Query
  • 37.
    /* file: routes/someRoute.js*/ var config = require('./mysql-config') , db = config.db; exports.checkExamStatus = function(req, res, next) { var sql = 'select * from some_talbe a where 1=1 '; var some_condition = req.params.some_condition; var cond = new Array(); if (req.params.some_condition != null) { sql += ' and a.some_column = ? '; cond.push(some_condition); } console.log('Query: ' + sql ); console.log('Cond: ' + cond); db.query(sql, cond, function(err, rows, fiels) { if(err) return next(err); res.render('simpleJsonResult', {result: rows}); }); }; Using MySQL connector - Query 2
  • 38.