You are on page 1of 185

Node.js Node.

js
Node.js Web Node.js Node.js

Node.js Node.js Web /

Node.js
BYVoid

14
100061315@ptpress.com.cn
http://www.ptpress.com.cn

80010001/16
11.75
249
1 5 000

2012 7 1
2012 7 1

ISBN 978-7-115-28399-3
45.00
(010)51095186604(010)67129223
(010)67171154

Node.js Node.js
Node.js Web

Node.js
6 Node.js
2JavaScript Node.js

1 Node.js
Node.js Node.js

JavaScript

2 Node.js

Node.js
Node.js

3 Node.js

Node.js Node.js
I/O
Node.js

4 Node.js
HTTP Node.js

10

5 Node.js Web
Express
Web 2.0

6 Node.js

Node.js

AJavaScript
JavaScript
JavaScript Node.js
JavaScript

BNode.js
Node.js

Node.js
Node.js
Node.js Node.js I/O
JavaScript

Java C

JavaScript Node.js
Node.js

Web
JavaScript JavaScript DOM

BOM
JavaScriptCJavaC++C# JavaScript
Node.js JavaScript

Web PHPASP.netRuby on RailsDjango


Node.js Node.js
I/O

Web Ajax
JavaScript
http://www.w3school.com.cn/js/ JavaScript

JavaScriptA
A
Node.js JavaScript
Mozilla JavaScripthttp://developer.mozilla.org/en/JavaScript/Guide

3 Node.js 4
Node.js API
5 Node.js
Web 6 Node.js

Node.js

BNode.js

Node.js
Node.js

http://www.byvoid.com/project/node
Node.js
Node.js

Node.js API http://nodejs.org/api/


CNodeJS http://cnodejs.org/

ituring.com.cn

10

Node.js Node.js
CNodeJS Node.js
Node.js

console.log('Node.js')

function hello() {
console.log('Hello, world!');
}

CNodeJS VMware

Rime

http://www.liyaos.com/
Dive into Python linuxtoy http://linuxtoy.org/
Rime WindowsLinux
Mac http://code.google.com/p/rimeime/

3
4

1 Node.js ......................................... 1
1.1 Node.js ............................................. 2
1.2 Node.js ......................................... 3
1.3 I/O ............................... 4
1.4 Node.js ............................................. 5
1.4.1
1.4.2

Node.js ............................. 5
Node.js PHP + Nginx ................... 6

1.5 JavaScript ............................................. 6


1.5.1 Netscape LiveScript ..................... 7
1.5.3

Java Javascript ............................. 7


JScript................... 8

1.5.4

ECMAScript ................. 8

1.5.5

........................... 9

1.5.6

JavaScript
.................................................. 9

1.5.2

1.6 CommonJS .................................................. 10


1.6.1 JavaScript .............. 10
CommonJS ................. 11
1.7 .................................................... 12
1.6.2

2 Node.js .......................... 13
2.1 ............................................ 14
2.2 .................................................... 14
2.2.1

Microsoft Windows
Node.js ............................................ 14

2.2.2

Linux Node.js ......... 16


Mac OS X Node.js.............. 16

2.2.3

2.3 ................................................ 17
2.3.1 POSIX ................... 17
2.3.2 Windows ................ 18

2.4 Node .................................. 18


2.5 ..................................... 19
2.6 .................................................... 21

3 Node.js .............................. 23
3.1 Node.js .................................. 24
3.1.1 Hello World .................................... 24
Node.js ....................... 25
3.1.3 HTTP ......................... 26
3.2 I/O ......................... 29
3.2.1 .................................... 29
3.1.2

........................................ 31
3.2.3 ................................................ 33
3.3 .................................................... 34
3.3.1 .................................... 35
3.2.2

3.3.2
3.3.3

............................. 35
............................................ 38

Node.js ........................... 41
............................................................
3.4
45
....................................
3.4.1
45
3.3.4

5
6
7
8
9
10
11
12
13

........................................ 47
3.4.3 Eclipse Node.js.............. 48

14

3.4.4 node-inspector
Node.js ............................................ 54

15

3.4.2

3.5 .................................................... 55

4 Node.js .............................. 57

16

4.1 .................................................... 58
4.1.1 ..................... 58

17

4.1.2 process......................................... 58
4.1.3 console......................................... 60

18

4.2 util .......................................... 61


4.2.1 util.inherits ............................. 61
4.2.2 util.inspect ............................. 62
4.3 events ..................................... 63
4.3.1 .................................... 64
4.3.2 error .................................... 65
4.3.3 EventEmitter .................... 65
4.4 fs............................................... 65
4.4.1 fs.readFile................................ 66
4.4.2 fs.readFileSync....................... 67
4.4.3 fs.open ......................................... 67
4.4.4 fs.read ......................................... 68
4.5 HTTP .............................. 70
4.5.1 HTTP ................................. 70
HTTP ................................. 74
4.6 .................................................... 77
4.5.2

Node.js Web ......... 79

5.1 .................................................... 80
5.1.1 http ............................. 82
5.1.2 Express ................................... 83
5.2 .................................................... 84
5.2.1 Express ................................... 84
5.2.2 ........................................ 85
5.2.3 .................................... 86
5.2.4 .................................... 87
5.3 .................................................... 89
5.3.1 ........................................ 89
5.3.2 ................................ 92
5.3.3 ........................................ 93
5.3.4 REST .................. 94
5.3.5 .................................... 95
5.4 .................................................... 97
5.4.1 ............................. 97
5.4.2 ................................ 98
5.4.3 ........................................ 99
5.4.4 ...................................... 100
5.4.5 ...................................... 100
5.5 .......................................... 102
5.5.1 ...................................... 102

5.5.2
5.5.3

...................................... 102
...................................... 103

5.5.4 Bootstrap .............................. 104


5.6 ...................................... 107
5.6.1 .................................. 107
5.6.2
5.6.3

...................................... 110
.................................. 111

.............................. 120
5.7 .................................................. 123
5.7.1 ...................................... 123
5.6.4

5.7.2
5.7.3

...................................... 125
...................................... 126

5.7.4 .............................................. 127


5.7.5 .......................................... 129
5.8 .................................................. 129

6 Node.js ............................ 131


6.1 .......................................... 132
6.1.1 .................................. 132
6.1.2

........................... 132

6.1.3

node_modules
...................................... 133

6.1.4

...................................... 134
...................................... 134

6.1.5

6.2 ...................................................... 135


6.2.1 .................................. 135
........................... 137
6.3 Node.js ..................................... 138
6.3.1 ...................................... 138
6.2.2

6.3.2 cluster ..................... 140


6.3.3 ...................................... 142
6.3.4 80 ................................. 143
6.4 Node.js ..................................... 144
6.5 .................................................. 146

A JavaScript ................... 147


B Node.js ............................. 167
................................................................ 175

1.1

Node.js

Node.js

10

Node.js

Node.js Node JavaScript


JavaScript PythonPerlPHPRuby
Node.js PythonPerlPHPRuby
Node.js
Node.js WebReal-time Web

I/O

Node.js Ryan Dahl Joyent Joyent


Ryan Dahl Node.js Joyent 2009
Node.js

node package managernpm


MySQLPostgreSQLMongoDB CSS
API VMware
Cloud Foundry Node.js20116 Joyent
Node.js Windows Windows Azure Node.jsNode.js
Web
Node.js

1.1

Node.js
Node.js PHPPythonPerlRuby

Node.js JavaScript CakePHPDjangoRailsNode.js


jQueryExtJS Node.js JavaScript
JavaScript PHPPython
PerlRuby
Node.js Web
Web Node.js
PHPPythonRuby on Rails ApacheNginx HTTP
Node.js LAMP
2110

Node.js JavaScript
JavaScriptJavaScript ECMAScript

1.2

Node.js

DOMBOM Mozilla JavaScript


Core JavaScript Client JavaScript JavaScript

Node.js JavaScript Core JavaScript ECMAScript


DOMBOM Client JavaScript Node.js

Node.js JavaScript
API Core JavaScript JavaScript
Node.js Node.js

JavaScript CommonJS CommonJS


JavaScript API
CommonJS JavaScript

CommonJS Node.js CommonJS

Node.js JavaScript V8 Google Chrome V8


JavaScript JITJust-in-time Compilation

Node.js
JavaScript JavaScript

1.2

Node.js

JavaScript Node.js Node.js


Node.js

Web
Web Socket
TCP/UDP

JavaScript

Node.js HTTP
PHPPerl PHP Apache

10

Node.js

HTTP HTTP CGI PHP


Node.js HTTP Node.js

Node.js Node.js
C/C++
C/C++

1.3

I/O
Node.js I/O

I/O Node.js I/O


Node.js
I/O

res = db.query('SELECT * from some_table');


res.output();

CPU

CPU

Node.js
db.query('SELECT * from some_table', function(res) {
res.output();
});

db.query
db.query

Node.js I/O

1.4

Node.js

1-1 Node.js

CPU I/O
Node.js
Web

5
1-1

Node.js
6

1.4

Node.js

1.4.1 Node.js
Node.js I/O Node.js

V8 JavaScript libev libeio I/O


1-2 Node.js
Node.js libev libeio libuv POSIX 9
libuv libev libeio epoll kqueue Windows libuv Windows

POSIXPortable Operating System Interface API POSIX


UNIXLinuxMac OS X

10

Node.js

IOCPInput/Output Completion Port

1-2

Node.js

1.4.2 Node.js PHP + Nginx


Snoopyxd Node.js PHP+Nginx 300030
hello world
PHP 36240.39
Node.js 76770.13

MySQL
PHP 12930.82
Node.js 29990.33

Node.js 6

1.5

JavaScript
Node.js JavaScript JavaScript

JavaScript

1.5

JavaScript

1.5.1 Netscape LiveScript

JavaScript 1995 Node.js JavaScript


1992 Nombas CC minus minusCmm
ScriptEaseScriptEase Espresso Page
ScriptEase

ScriptEase Brendan Eich

LiveWire LiveWire LiveScript


Web

1.5.2 Java Javascript


JavaScript Java applet Sun
Java Java applet Sun
Java applet

Sun LiveScript Navigator 2.0 LiveScript


JavaScript Sun JavaScript Java applet HTML
Java applet
Netscape

Java JavaScript
Java JavaScript
1-3 Java

8
1-3

Java

Brendan Eich JavaScript

applet
Java
Brendan Eich JavaScript at Ten YearsJavaScript 10
Dont let marketing name your language.

10

Node.js

1.5.3 JScript
Internet Explorer 3 Windows 95 OSR2
Navigator
Internet Explorer3
Internet Explorer 3
JavaScript JScript
VBScriptJScript JavaScript
1-4 Windows 95 Internet Explorer 3

1-4

Windows 95 Internet Explorer 3

1.5.4 ECMAScript
JavaScript
Internet Explorer JavaScript
1996JavaScript ECMA
ECMA ECMA-262 ECMAScript
ECMAScript ISO-16262 ECMAScript

1.5

JavaScript

JavaScript
ECMAScript 2009 12

ECMAScript 52012 ECMAScript 3 Chrome


Firefox ECMAScript 5

2
ECMAScript
C++ JavaScript ActionScript
QtScriptWMLScript ECMAScript

1.5.5
ECMAScript JavaScript JavaScript

JavaScript

JavaScript DOM 5
BOMCSS World Wide Web ConsortiumW3C

1.5.6 JavaScript
JavaScript Brendan Eich Navigator
SpiderMonkeySpiderMonkey Mozilla Firefox 1.0~3.0

Firefox 3.5 TraceMonkey4.0 JaegerMonkeyGoogle Chrome


JavaScript V8 V8 Node.js Internet Explorer 9
JavaScript Chakra
JavaScript

JavaScript
Shockley 2008 JavaScript
Node.js

ActionScript Adobe Flash Adobe


QtScript Qt 4.3.0
WMLScript WAP WMLWireless Markup Language
KJS KonquerorNitro SafariCarakan Opera JavaScript

10

10

Node.js

2008 Mozilla Firefox Firefox 3.0 JavaScript


JavaScript WebKit Safari 4 JavaScript
SquirrelFish NitroGoogle Chrome
JavaScript WebKit Squirrelfish Extreme Mozilla
TraceMonkey Chrome JavaScript Chrome 2
V8 V8
JavaScript
Internet Explorer
JavaScript
JavaScript
JavaScript

JavaScript
JavaScript JavaScript ECMAScript 6
CoffeeScript JavaScript
Google JavaScript Dart
JavaScript

1.6

CommonJS

1.6.1 JavaScript
Node.js JavaScript
JavaScript JavaScript
JavaScript JavaScript
JavaScript ASP
2000 ASP JScript JScript
JScript JavaScript
VBScript JScript LAMP Web 2.0 Ajax
JavaScript JavaScript

WebKit Safari KHTML KJS WebKit


WebCore JavaScriptCore JavaScript WebKit
WebCore

1.6 CommonJS

11

JavaScript JavaScript
Node.js RingoJS Rhino JavaScript

CouchDBMongoDB JavaScript JSON


JavaScript

1.6.2 CommonJS
JavaScript ECMAScript
JavaScript CommonJS CommonJS
API JavaScript CommonJS

C++ CommonJS API


C++
CommonJS Node.js 1-5

CommonJS

1-5

CommonJS

CommonJS modulespackagessystembinary
consoleencodingsfilesystemssockets
unit testing
Modules/1.0Modules/1.1Modules/1.1.1Packages/1.0System/1.0

10

12

Node.js

Node.js CommonJS CommonJS Modules/1.0


Node.js CommonJS Node.js
CommonJS Node.js
CommonJS Node.js CommonJS

1.7

Node.js: http://nodejs.org/
selectiocpepollkqueueI/O: http://blog.csdn.net/shallwake/

article/details/5265287
node.jsphp: http://snoopyxdy.blog.163.com/blog/static/6011744

0201183101319257/
RingoJS vs. Node.js: Runtime Values: http://hns.github.com/2010/09/21/benchmark. html
Update on my Node.js Memory and GC Benchmark: http://hns.github.com/2010/ 09/29/

benchmark2.html
JavaScript at Ten Years: http://dl.acm.org/citation.cfm?id=1086382
QtScript : http://qt-project.org/doc/qt-4.8/qtscript.html
WebKit Open Source Project : http://www.webkit.org/
CommonJS API Specifications : http://www.commonjs.org/specs/
RingoJS : http://ringojs.org/
MongoDB : http://www.mongodb.org/
CouchDB : http://couchdb.apache.org/
Persevere : http://www.persvr.org/
JavaScript
JavaScript 3
Nicholas C. Zakas
JavaScript 5
Flanagan David

2.1

13

Node.js

10

14

2 Node.js

Node.js
LinuxWindowsMac OS X Node.js
POSIX Windows Node.js
npmNode.js

Node.js

2.1

Node.js POSIX GNU/LinuxMac OS X

Solaris Node.js Windows cygwin 0.6


Windows
2009Node.js

Node.js Node.js

Windows Node.js
Node.js 0.6 Windows cygwin
Windows Azure
Node.js
Node.js
Node.js Windows POSIX npm
C/C++
Linux Windows
Windows Node.js
Node.js Node.js Windows

Node.js

2.2

2.2.1 Microsoft WindowsNode.js


Windows Node.js http://nodejs.orgDownload
Windows Installer2-1

2.2

15

Next

4
2-1

Windows Node.js

Node.js C:\Program Files\nodejs


C:\Program Files (x86)\nodejs64 PATH

Windows node
cmd node
Node.js 2-2

9
2-2

Windows Node.js

Node.js npm 2-2


npm

10

16

2 Node.js

2.2.2 Linux Node.js


Node.js Linux
Linux Node.js

Node.js2-1
2-1 Linux Node.js
Linux

Debian/Ubuntu

apt-get install nodejs

Fedora/RHEL/CentOS/Scientific Linux

yum install nodejs

openSUSE

zypper install nodejs

Arch Linux

pacman -S nodejs

Node.js
https://github.com/joyent/node/wiki/Installing-Node.js-via-packagemanager

2.2.3 Mac OS XNode.js


Node.js Mac OS X http://nodejs.org Download
Macintosh Installer2-3

2-3

Mac OS X Node.js

Node.js npm /usr/local/bin

2.3

17

node Node.js -bash:


node: command not found

Node.js

2.3

Node.js 0.6

http://nodejs.orgDownload

Source Code
https://github.com/joyent/node/zipball/master git clone git:
//github.com/joyent/node.git git

2.3.1 POSIX
POSIX Node.js
C++ gcc clang/LLVM

Python 2.5 Python 3


libssl-dev SSL/TLS

Linux g++ Node.js Debian/Ubuntu


apt-get install g++ g++ Fedora/Redhat/CentOS yum
install gcc-c++
Mac OS X Xcode Xcode
https://developer.apple.com/xcode/
Mac OS X Linux Python
python --version Python Python 2.7.2
2.5 command not found
Python http://python.org/
libssl-dev OpenSSL SSL/TLS Mac OS
X Xcode libssl-dev Debian/Ubuntu apt-get install
libssl-dev Fedora/Redhat/CentOS yum install
openssl-devel http://openssl.org/
Node.js
./configure
make
sudo make install

10

18

2 Node.js

20Node.js npm
Mac OS X homebrew Node.js http://mxcl.
github.com/homebrew/ homebrew
Node.js
brew install node

2.3.2 Windows
Node.js Windows Microsoft Visual Studio Visual
Studio Visual Studio Express Python 22.5
3.0http://python.org/ Python PATH
python.exe
Node.js
C:\Users\byvoid\node-v0.6.12>vcbuild.bat release
['-f', 'msvs', '-G', 'msvs_version=2010', '.\\node.gyp', '-I', '.\\common.gypi', '--depth=.',
'-Dtarget_Project files generated.
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppBuild.targets(1151,5):
warning MSB8012: http_parser.vcxproj -> C:\Users\byvoid\node-v0.6.12\
Release\http_parser.lib
js2c, and also js2c_experimental
node_js2c
...

20 Release node.exe
Node.js node.exe Node.js
node.exe Node.js PATH
node.exe node
npm

2.4

Node
Node npm Node.js PHP

PearPython PyPI npm JavaScript Node.js


Node.js Node.js
npm Node.js 0.6 npm Windows
Mac npm
Windows POSIX --without-npm
npm http://npmjs.org/ npm

2.5

19

curl http://npmjs.org/install.sh | sh

root sudo
curl http://npmjs.org/install.sh | sudo sh

git npm http://npmjs.org/doc/


README.html

2.5

Node.js API

Node.js

Node.js Node Node Version


Managernvm nvm
https://github.com/creationix/nvm https://github.com/visionmedia/n

visionmedia/n Node
n Node n

Node.js npm npm install -g n

n n Node.js npm
n Node.js bash npm
https://github.com/visionmedia/n make
install
n Windows

n n --help
$ n --help

Usage: n [options] [COMMAND] [config]

n nvm n

10

20

2 Node.js
Commands:
n
n
n
n
n
n
n
n

latest [config ...]


<version> [config ...]
use <version> [args ...]
bin <version>
rm <version ...>
--latest
ls

Output versions installed


Install or activate the latest node release
Install and/or use node <version>
Execute node <version> with [args ...]
Output bin path for <version>
Remove the given version(s)
Output the latest node version available
Output the versions of node available

Options:
-V, --version
-h, --help

Output current version of n


Display help information

Aliases:
which
use
list

rm
bin
as
ls

n Node.jsn http://nodejs.org

$ n 0.7.5
######################################################################## 100.0%
{ 'target_defaults': { 'cflags': [],
'defines': [],
'include_dirs': [],
'libraries': ['-lz']},
'variables': { 'host_arch': 'x64',
'node_install_npm': 'true',
'node_install_waf': 'true',
'node_prefix': '/usr/local/n/versions/0.7.5',
'node_shared_cares': 'false',
'node_shared_v8': 'false',
'node_use_dtrace': 'false',
'node_use_openssl': 'true',
'node_use_system_openssl': 'false',
'target_arch': 'x64',
'v8_use_snapshot': 'true'}}
creating ./config.gypi
creating ./config.mk
make -C out BUILDTYPE=Release

2.6

21

CC(target) /usr/local/n/node-v0.7.5/out/Release/obj.target/http_parser/deps/
http_parser/http_parser.o
LIBTOOL-STATIC /usr/local/n/node-v0.7.5/out/Release/libhttp_parser.a
...

n Node.js /usr/local/n/versions/

n Node.js*
Node.js node

$ n
0.6.11
* 0.7.5

n Node.js
node n
$ n 0.6.11
* 0.6.11
0.7.5
$ node -v
v0.6.11

n use script.js Node.js

n use 0.6.11 script.js

7
n Node.js
n Node.js
Node.js

n https://github.com/visionmedia/n

2.6

Building and Installing Node.js: https://github.com/joyent/node/wiki/Installation


Node package manager: http://npmjs.org/doc/README.html
Node version management: https://github.com/visionmedia/n

10

22

2 Node.js

Node.js: Node.js & NPM: http://www.infoq.com/cn/

articles/nodejs-npm-install-config
Node.js Now Runs Natively on Windows: http://www.infoq.com/news/2011/11/Nodejs-

Windows
Node Web
David Herron
Mac OS X Lion node.js : http://dreamerslab.com/blog/tw/

how-to-setup-a-node- js-development-environment-on-mac-osx-lion/

3.1 Node.js

23

Node.js

10

24

Node.js

Node.js Node.js
Node.js
Node.js
Node.js Node.js
Node.js
I/O

3.1

Node.js
Node.js github

Node.js

3.1.1 Hello World


Node.js
console.log('Hello World');

helloworld.js helloworld.js
node helloworld.js

Hello World
console Node.js
console.logconsole.error console.log
C printf %d%s

//consolelog.js
console.log('%s: %d', 'Hello', 25);

Hello: 25 console
4.1.3

3.1 Node.js

25

3.1.2 Node.js

Hello World node node --help

Usage: node [options] [ -e script | script.js ] [arguments]


node debug script.js [arguments]
Options:
-v, --version
-e, --eval script
-p, --print
--v8-options
--vars
--max-stack-size=val

print node's version


evaluate script
print result of --eval
print v8 command line options
print various compiled-in variables
set max v8 stack size (bytes)

Environment variables:
NODE_PATH
';'-separated list of directories
prefixed to the module search path.
NODE_MODULE_CONTEXTS
Set to 1 to load modules in their own
global contexts.
NODE_DISABLE_COLORS
Set to 1 to disable colors in the REPL

Documentation can be found at http://nodejs.org/

node Node.js node script.js


script.js

node --help Hello


World

$ node -e "console.log('Hello World');"


Hello World

node -e
node REPL

REPL Read-eval-print loop Python


python Python IDLE shell
Node.js node JavaScript

shell

.js script.txt node script.txt


.js JavaScript

10

26

Node.js

$ node
> console.log('Hello World');
Hello World
undefined
> consol.log('Hello World');
ReferenceError: consol is not defined
at repl:1:1
at REPLServer.eval (repl.js:80:21)
at repl.js:190:20
at REPLServer.eval (repl.js:87:5)
at Interface.<anonymous> (repl.js:182:12)
at Interface.emit (events.js:67:17)
at Interface._onLine (readline.js:162:10)
at Interface._line (readline.js:426:8)
at Interface._ttyWrite (readline.js:603:14)
at ReadStream.<anonymous> (readline.js:82:12)

REPL >Node.js
REPL
undefined console.log
REPL Ctrl + C
Node.js REPL
node REPL

3.1.3 HTTP
Hello World

Node.js
Node.js ASPPHP
PHP PHP HTTP
ApacheIIS Nginx PHP HTTP
FastCGI PHP HTTP PHP
Node.js3-1
Node.js HTTP
Node.jsHTTP

3.1 Node.js

27

3
3-1

Node.js PHP

HTTP app.js

//app.js
var http = require('http');

http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<h1>Node.js</h1>');
res.end('<p>Hello World</p>');
}).listen(3000);
console.log("HTTP server is listening at port 3000.");

node app.js http://127.0.0.1:30003-2

3-2

Node.js HTTP

10

28

Node.js

Node.js HTTP Node.js


http HTTP 3000

Hello World Ctrl +


C listen Node.js

supervisor
PHP PHP
Node.js HTTP
Node.js Node.js
PHP
Node.js

supervisor Node.js
npm supervisor
$ npm install -g supervisor

Linux Mac npm


supervisor sudo npm install -g
supervisor

supervisor app.js
$ supervisor app.js
DEBUG: Running node-supervisor with
DEBUG:
program 'app.js'
DEBUG:
--watch '.'
DEBUG:
--extensions 'node|js'
DEBUG:
--exec 'node'
DEBUG: Starting child process with 'node app.js'
DEBUG: Watching directory '/home/byvoid/.' for changes.
HTTP server is listening at port 3000.

DEBUG: crashing child


DEBUG: Starting child process with 'node app.js'
HTTP server is listening at port 3000.

supervisor

3.2 I/O

3.2

29

I/O

Node.js I/O I/O


I/O

3.2.1
block I/O
CPU

I/O
CPU I/O
I/OSynchronous I/O I/O Blocking I/O

I/O Asynchronous I/O I/O Non-blocking I/O


I/O I/O I/O
I/O
I/O I/O

I/O

CPU 100%
I/O
CPU
I/O CPU CPU

Node.js Node.js

3-3 3-4 I/O I/O


I/O I/O

I/O I/O

10

30

Node.js

3-3

I/O

3-4

I/O

3.2 I/O

31

I/O I/O
I/O

CPU

async
6.2.2
3-1 I/O I/O

3-1 I/O I/O


I/O

I/O

CPU

CPU

CPU

CPU

CPU

CPU

3.2.2
Node.js

//readfile.js
var fs = require('fs');
fs.readFile('file.txt', 'utf-8', function(err, data) {
if (err) {
console.error(err);
} else {
console.log(data);
}
});
console.log('end.');

end.
Contents of the file.

lightweight thread

10

32

Node.js

Node.js API
//readfilesync.js
var fs = require('fs');
var data = fs.readFileSync('file.txt', 'utf-8');
console.log(data);
console.log('end.');

$ node readfilesync.js
Contents of the file.
end.

fs.readFileSync
data
data end.
end.
Node.js I/O fs.readFile

JavaScript
fs.readFile JavaScript

//readfilecallback.js
function readFileCallBack(err, data) {
if (err) {
console.error(err);
} else {
console.log(data);
}
}
var fs = require('fs');
fs.readFile('file.txt', 'utf-8', readFileCallBack);
console.log('end.');

fs.readFile I/O

fs I/O
end.
file.txt

3.2 I/O

33

Node.js API Node.js


I/O

3.2.3

Node.js I/O
EventEmitter fs.readFile http.createServer
EventEmitter EventEmitter

//event.js
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter();
event.on('some_event', function() {
console.log('some_event occured.');
});
setTimeout(function() {
event.emit('some_event');
}, 1000);

1 some_event occured. event

some_event setTimeout 1000


event some_event some_event

4.3.1 EventEmitter

Node.js
Node.js Node.js
Node.js
I/O

emit
3-5
Node.js Ruby EventMachine::run()

Node.js Node.js libev libev


ev_ioev_timerev_signalev_idle Node.js
EventEmitter libev Node.js Ticklibev

10

34

Node.js

3-5

3.3

ModulePackage Node.js

JavaScript HTML
script Node.js require

Node.js CommonJS
Node.js

Node.js

3.3

35

3.3.1

Node.js
Node.js JavaScript JSON C/C++ 3
var http = require('http') http
Node.js C++ JavaScript
require

3.3.2

1.
Node.js

Node.js exports require


exports require
exports

module.js
//module.js
var name;
exports.setName = function(thyName) {
name = thyName;
};

exports.sayHello = function() {
console.log('Hello ' + name);
};

getmodule.js

//getmodule.js
var myModule = require('./module');

10

36

Node.js

myModule.setName('BYVoid');
myModule.sayHello();

node getmodule.js
Hello BYVoid

module.js exports setName sayHello


getmodule.js require('./module')
module.js exports

npm

2.

require require

getmodule.js
//loadmodule.js
var hello1 = require('./module');
hello1.setName('BYVoid');
var hello2 = require('./module');
hello2.setName('BYVoid 2');
hello1.sayHello();

Hello BYVoid 2 hello1 hello2


hello1.setName hello2.setName

3. exports

//singleobject.js
function Hello() {
var name;
this.setName = function (thyName) {
name = thyName;
};

3.3

37

this.sayHello = function () {
console.log('Hello ' + name);
};

};
exports.Hello = Hello;

require('./singleobject').Hello

Hello
//hello.js

function Hello() {
var name;
this.setName = function(thyName) {
name = thyName;
};
this.sayHello = function() {
console.log('Hello ' + name);
};

};
module.exports = Hello;

//gethello.js
var Hello = require('./hello');
hello = new Hello();
hello.setName('BYVoid');
hello.sayHello();

module.exports = Hello exports.Hello=


Hello Hello

exports

exports {}
9
Hello

10

38

Node.js

exports module.exports
exports module.exports
module
module.exports

3.3.3
Node.js C/C++ Java/.Net
Node.js
CommonJS npm
Node.js JSON package.json
CommonJS
package.json
bin
JavaScript lib
doc
test

Node.js package.json
CommonJS
1.
JavaScript

somepackage index.js
//somepackage/index.js
exports.hello = function() {
console.log('Hello.');
};

somepackage getpackage.js
//getpackage.js
var somePackage = require('./somepackage');
somePackage.hello();

3.3

39

node getpackage.js Hello.

package.json
2. package.json
somepackage package.json

{
"main" : "./lib/interface.js"
}

index.js interface.js lib

Node.js package.json main


package.json main index.js index.node

package.json CommonJS package.json

name

description

version
keywords
maintainers nameemail
web

contributorsmaintainers

bugsbug

licenses type url

repositories type git

url path

Semantic Versioning Gravatars GitHub Tom Preston-Werner

10

40

Node.js

dependencies

CommonJS package.json
{
"name": "mypackage",
"description": "Sample package for CommonJS. This package demonstrates the required
elements of a CommonJS package.",
"version": "0.7.0",
"keywords": [
"package",
"example"
],
"maintainers": [
{
"name": "Bill Smith",
"email": "bills@example.com",
}
],
"contributors": [
{
"name": "BYVoid",
"web": "http://www.byvoid.com/"
}
],
"bugs": {
"mail": "dev@example.com",
"web": "http://www.example.com/bugs"
},
"licenses": [
{
"type": "GPLv2",
"url": "http://www.example.org/licenses/gpl.html"
}
],
"repositories": [
{
"type": "git",
"url": "http://github.com/BYVoid/mypackage.git"
}
],
"dependencies": {
"webkit": "1.2",
"ssl": {
"gnutls": ["1.0", "2.0"],
"openssl": "0.9.8"
}
}
}

3.3

41

3.3.4 Node.js

Node.jsnpm Node.js Node.js


Node.js npm

1.
npm
npm [install/i] [package_name]

express
$ npm install express

$ npm i express

npm http GET https://registry.npmjs.org/express


npm http 304 https://registry.npmjs.org/express
npm http GET https://registry.npmjs.org/mime/1.2.4
npm http GET https://registry.npmjs.org/mkdirp/0.3.0
npm http GET https://registry.npmjs.org/qs
npm http GET https://registry.npmjs.org/connect
npm http 200 https://registry.npmjs.org/mime/1.2.4
npm http 200 https://registry.npmjs.org/mkdirp/0.3.0
npm http 200 https://registry.npmjs.org/qs
npm http GET https://registry.npmjs.org/mime/-/mime-1.2.4.tgz
npm http GET https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz
npm http 200 https://registry.npmjs.org/mime/-/mime-1.2.4.tgz
npm http 200 https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz
npm http 200 https://registry.npmjs.org/connect
npm http GET https://registry.npmjs.org/formidable
npm http 200 https://registry.npmjs.org/formidable
express@2.5.8 ./node_modules/express
-- mime@1.2.4
-- mkdirp@0.3.0
-- qs@0.4.2
-- connect@1.8.5

express node_modules npm

npm Node.js pip Pythongem Rubypear PHPCPAN Perl apt-get


Debian/Ubutnuyum Fedora/RHEL/CentOShomebrew Mac OS X

10

42

Node.js

express express mimemkdirp


qs connect

2.
npmhttp://npmjs.orgnode_modules

Ruby gem Python pip npm


gem pip
npm npm

API
npm npm
install node_modules Node.js

require node_modules npm

npm
npm [install/i] -g [package_name]

-g supervisor
npm install -g supervisor supervisor

PATH
supervisor supervisor script.js PATH
supervisornpm node_modules
bin PATH
npm /usr/local/lib/node_modules/ package.json
bin /usr/local/bin//usr/local/bin/ PATH
supervisor script.js
JavaScript require
require /usr/local/lib/node_modules/ 6

3.3

43

3-2

3-2

require

PATH

Linux/Mac npm install -g root


/usr/local/lib/node_modules/
3.
npm npm link

require npm link


npm install -g express express

$ npm link express


./node_modules/express -> /usr/local/lib/node_modules/express

node_modules

npm link Windows

npm link
package.json npm link

4.
npm pipgempear
npm npm CommonJS CommonJS

npm init
package.json byvoidmodule
npm init

10

44

Node.js

$ npm init
Package name: (byvoidmodule) byvoidmodule
Description: A module for learning perpose.
Package version: (0.0.0) 0.0.1
Project homepage: (none) http://www.byvoid.com/
Project git repository: (none)
Author name: BYVoid
Author email: (none) byvoid.kcp@gmail.com
Author url: (none) http://www.byvoid.com/
Main module/entry point: (none)
Test command: (none)
What versions of node does it run on? (~0.6.10)
About to write to /home/byvoid/byvoidmodule/package.json
{
"author": "BYVoid <byvoid.kcp@gmail.com> (http://www.byvoid.com/)",
"name": "byvoidmodule",
"description": "A module for learning perpose.",
"version": "0.0.1",
"homepage": "http://www.byvoid.com/",
"repository": {
"url": ""
},
"engines": {
"node": "~0.6.12"
},
"dependencies": {},
"devDependencies": {}
}
Is this ok? (yes) yes

byvoidmodule npm package.json


index.js
npm adduser
npm whoami

package.json npm publish


http://search.npmjs.org/
npm install byvoidmodule 3-6 npmjs.
org
package.json version
npm publish
npm unpublish

3.4

45

3-6

3.4

npm

bug bug
C/C++ Visual Studiogdb
JavaScript

FireBugChrome JavaScript

Node.js V8

Node.js

3.4.1

Node.js
var a = 1;
var b = 'world';

10

46

Node.js

var c = function(x) {
console.log('hello ' + x + a);
};
c(b);

node debug debug.js


< debugger listening on port 5858
connecting... ok
break in /home/byvoid/debug.js:1
1 var a = 1;
2 var b = 'world';
3 var c = function(x) {
debug>

Node.js
3-3
3-3 Node.js

run

restart

cont, c

next, n

step, s

out, o

setBreakpoint(), sb()

setBreakpoint(f()), sb(...)

setBreakpoint(script.js, 20), sb(...)

script.js 20

clearBreakpoint, cb(...)

backtrace, bt

list(5)

watch(expr)

expr

unwatch(expr)

expr

watchers

repl

kill

scripts

version

V8

3.4

47

$ node debug debug.js


< debugger listening on port 5858
connecting... ok
break in /home/byvoid/debug.js:1
1 var a = 1;
2 var b = 'world';
3 var c = function (x) {
debug> n
break in /home/byvoid/debug.js:2
1 var a = 1;
2 var b = 'world';
3 var c = function (x) {
4
console.log('hello ' + x + a);
debug> sb('debug.js', 4)
1 var a = 1;
2 var b = 'world';
3 var c = function (x) {
* 4
console.log('hello ' + x + a);
5 };
6 c(b);
7 });
debug> c
break in /home/byvoid/debug.js:4
2 var b = 'world';
3 var c = function (x) {
* 4
console.log('hello ' + x + a);
5 };
6 c(b);
debug> repl
Press Ctrl + C to leave debug repl
> x
'world'
> a + 1
2
debug> c
< hello world1
program terminated

3.4.2
V8 TCP Node.js

node --debug[=port] script.js


node --debug-brk[=port] script.js

10

48

Node.js

node --debug 5858

--debug=1234 1234 --debug

--debug-brk

//
$ node --debug-brk debug.js
debugger listening on port 5858
//
$ node debug 127.0.0.1:5858
connecting... ok
debug> n
break in /home/byvoid/debug.js:2
1 var a = 1;
2 var b = 'world';
3 var c = function (x) {
4
console.log('hello ' + x + a);
debug>

node debug debug.js Node.js

3.4.3 Eclipse Node.js


Node.js V8 IDE
EclipseEclipse Java
Eclipse Node.js

1.
Eclipse JDK http://www.oracle.com/technetwork/java/
javase/downloads/index.html http://www.eclipse.org/downloads/ Eclipse
Eclipse HelpInstall New Software...
Add...Add Repository Location
http://chromedevtools.googlecode.com/svn/update/dev/Name Chrome Developer
OK3-73-83-9

3.4

49

3-7

HelpInstall New Software...

6
3-8

Add...

3-9

Add Repository

Work withChrome Developer


Google Chrome Developer ToolsNext3-10

10

50

Node.js

3-10

Google Chrome Developer Tools

Eclipse Next3-11

3-11

3.4

51

LicenseI accept the terms of the license agreementsNext3-12

4
3-12

License

Eclipse 3-13

7
3-13

Eclipse Restart NowV8


3-14

3-14

Restart Now

10

52

Node.js

2. Eclipse Node.js
Eclipse Node.js Debug perspective3-15
Debug Debug Configurations...3-16
Standalone V8 VMNew
NameNodeDebugHostPortApply3-17

3-15

3-16

Debug perspective

Debug Configurations...

3.4

53

4
3-17

Standalone V8 VM

node --debug-brk=5858 debug.js

Eclipse 3-18

3-18

10

54

Node.js

Eclipse IDE Node.js


Eclipse Eclipse

3.4.4 node-inspector Node.js


Node.js node-inspector
node-inspector Node.js

npm install -g node-inspector node-inspector


node --debug-brk=5858 debug.js
node-inspector
$ node-inspector

http://127.0.0.1:8080/debug?port=5858 Web
3-19

3-19

node-inspector

node-inspector

3.5

55

node-inspector WebKit Web Inspector ChromeSafari


WebKit Firefox Internet Explorer

3.5

Node Web
David Herron
node-supervisor: https://github.com/isaacs/node-supervisor
Node.js is Cancer: http://teddziuba.com/2011/10/node-js-is-cancer.html

Straight Talk on Event Loops: http://teddziuba.com/2011/10/straight-talk-on-event- loops.

html
nodejs Timer & Tick : http://club.cnodejs.org/topic/4f16442ccae1f4aa2700109b

node.jsnode.js: http://www.jiangmiao.org/blog/

2491.html
Node.js: https://www.ibm.com/developerworks/cn/web/1201_wangqf_nodejs/

libev: http://libev.schmorp.de

Node.jsNode.js: http://www.infoq.com/cn/articles/

nodejs-module-mechanism
npmPath: http://blog.goddyzhao.me/post/

9835631010/no-direct-command-for-local-installed-command-line-modul
CommonJS /1.0: http://wiki.commonjs.org/wiki/Packages/1.0
Semantic Versioning 2.0.0-rc.1: http://semver.org/
Symlink a package folder npm: http://npmjs.org/doc/link.html

Publish a package npm: http://npmjs.org/doc/publish.html


Node.jsnpm: http://www.cnblogs.com/piyeyong/

archive/2011/12/ 30/2308153.html
V8 debugger JSON based protocol: http://code.google.com/p/v8/wiki/DebuggerProtocol

node-inspector: https://github.com/dannycoates/node-inspector

10

4.1

57

Node.js

10

58

Node.js

Node.js Node.js
API




HTTP

4.1

JavaScript Global Object

JavaScript window
Node.js global global global

Node.js global consoleprocess

4.1.1
global ECMAScript

Node.js

var

4.1.2 process
process global Node.js

4.1

59

process
process.argv node

console.log(process.argv);

argv.js
$ node argv.js 1991 name=byvoid --v "Carbo Kuo"
[ 'node',
'/home/byvoid/argv.js',
'1991',
'name=byvoid',
'--v',
'Carbo Kuo' ]

process.stdout console.log()

process.stdout.write()
process.stdin

process.stdin.resume();
process.stdin.on('data', function(data) {
process.stdout.write('read from console: ' + data.toString());
});

process.nextTick(callback)Node.js

callback

Node.js I/O
Node.js
CPU Node.js
process.nextTick()

function doSomething(args, callback) {


somethingComplicated(args);
callback();
}
doSomething(function onEnd() {
compute();
});

10

60

Node.js

compute() somethingComplicated()
doSomething() somethingComplicated()
onEnd() compute() process.nextTick()

function doSomething(args, callback) {


somethingComplicated(args);
process.nextTick(callback);
}
doSomething(function onEnd() {
compute();
});

setTimeout(fn,0) process.nextTick(callback)

process
processprocess.platform
process.pidprocess.execPathprocess.memoryUsage() POSIX

http://nodejs.org/api/process.html

4.1.3 console
console Internet Explorer JScript

Node.js
console stdoutstderr
console.log()console.log

C printf()

console.log('Hello world');
console.log('byvoid%diovyb');
console.log('byvoid%diovyb', 1991);

4.2 util

61

Hello world
byvoid%diovyb
byvoid1991iovyb

console.error() console.log()
console.trace()

console.trace();

Trace:
at
at
at
at
at
at
at

4.2

3
Object.<anonymous> (/home/byvoid/consoletrace.js:1:71)
Module._compile (module.js:441:26)
Object..js (module.js:459:10)
Module.load (module.js:348:31)
Function._load (module.js:308:12)
Array.0 (module.js:479:10)
EventEmitter._tickCallback (node.js:192:40)

util

util Node.js JavaScript

4.2.1 util.inherits

util.inherits(constructor, superConstructor)

JavaScript JavaScript
A

util.inherits
var util = require('util');

function Base() {
this.name = 'base';
this.base = 1991;
this.sayHello = function() {
console.log('Hello ' + this.name);
};

}
Base.prototype.showName = function() {
console.log(this.name);

10

62

Node.js

};
function Sub() {
this.name = 'sub';
}
util.inherits(Sub, Base);
var objBase = new Base();
objBase.showName();
objBase.sayHello();
console.log(objBase);
var objSub = new Sub();
objSub.showName();
//objSub.sayHello();
console.log(objSub);

Base Base SubBase


util.inherits
base
Hello base
{ name: 'base', base: 1991, sayHello: [Function] }
sub
{ name: 'sub' }

Sub Base base


sayHello Sub console.log
objSub.sayHello();
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Object #<Sub> has no method 'sayHello'
at Object.<anonymous> (/home/byvoid/utilinherits.js:29:8)
at Module._compile (module.js:441:26)
at Object..js (module.js:459:10)
at Module.load (module.js:348:31)
at Function._load (module.js:308:12)
at Array.0 (module.js:479:10)
at EventEmitter._tickCallback (node.js:192:40)

4.2.2 util.inspect
util.inspect(object,[showHidden],[depth],[colors])

object

4.3 events

63

showHidden true
depth

depth2 null
color true ANSI

util.inspect
toString
var util = require('util');

function Person() {
this.name = 'byvoid';
this.toString = function() {
return this.name;
};

}
var obj = new Person();

console.log(util.inspect(obj));
console.log(util.inspect(obj, true));

{ name: 'byvoid', toString: [Function] }


{ toString:
{ [Function]
[prototype]: { [constructor]: [Circular] },
[caller]: null,
[length]: 0,
[name]: '',
[arguments]: null },
name: 'byvoid' }

utilutil.isArray()util.isRegExp()

util.isDate()util.isError() util.format()util.
debug() http://nodejs.org/api/util.html

4.3

events

events Node.js
Node.js

Node.js events

10

64

Node.js

Node.js

4.3.1
events events.EventEmitterEventEmitter

EventEmitter
EventEmitter

var events = require('events');


var emitter = new events.EventEmitter();
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener1', arg1, arg2);
});
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener2', arg1, arg2);
});
emitter.emit('someEvent', 'byvoid', 1991);

listener1 byvoid 1991


listener2 byvoid 1991

emitter someEvent
someEvent

EventEmitterEventEmitterAPI
EventEmitter.on(event, listener)

event listener
EventEmitter.emit(event, [arg1], [arg2], [...]) event

EventEmitter.once(event, listener)

EventEmitter.removeListener(event, listener)

listener

4.4 fs

65

EventEmitter.removeAllListeners([event])

event

API http://nodejs.org/api/events.html

4.3.2 error

EventEmitter error

error error EventEmitter


Node.js error

var events = require('events');


var emitter = new events.EventEmitter();

emitter.emit('error');

node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Uncaught, unspecified 'error' event.
at EventEmitter.emit (events.js:50:15)
at Object.<anonymous> (/home/byvoid/error.js:5:9)
at Module._compile (module.js:441:26)
at Object..js (module.js:459:10)
at Module.load (module.js:348:31)
at Function._load (module.js:308:12)
at Array.0 (module.js:479:10)
at EventEmitter._tickCallback (node.js:192:40)

4.3.3 EventEmitter
EventEmitter fsnet

http EventEmitter

JavaScript
EventEmitter

4.4

fs
fs

10

66

Node.js

POSIX fs
fs.readFile()
fs.readFileSync() fs fs

4.4.1 fs.readFile
fs.readFile(filename,[encoding],[callback(err,data)])

filename encoding
callback
encoding callback err dataerr
data encodingdata
data Buffer
content.txt
var fs = require('fs');
fs.readFile('content.txt', function(err, data) {
if (err) {
console.error(err);
} else {
console.log(data);
}
});

content.txt UTF-8 Text


<Buffer 54 65 78 74 20 e6 96 87 e6 9c ac e6 96 87 e4 bb b6 e7 a4 ba e4 be 8b>

data Buffer
fs.readFile encoding
var fs = require('fs');
fs.readFile('content.txt', 'utf-8', function(err, data) {
if (err) {
console.error(err);
} else {
console.log(data);
}
});

Text

4.4 fs

67

err Error content.txt

{ [Error: ENOENT, no such file or directory 'content.txt'] errno: 34, code: 'ENOENT',
path: 'content.txt' }

2
Node.js
err
err null
undefinederr Error

4.4.2 fs.readFileSync
fs.readFileSync(filename, [encoding]) fs.readFile

fs.readFile
fs try catch
I/O Node.js

4.4.3 fs.open

fs.open(path, flags, [mode], [callback(err, fd)]) POSIX open

C fopen path
flags
r

r+
w
w+
a

a+

mode 0666

fd

POSIX 0754
7
5 4
-rwxr-xr--

10

68

Node.js

4.4.4 fs.read
fs.read(fd, buffer, offset, length, position, [callback(err, bytesRead,
buffer)]) POSIX read fs.readFile fs.read

fd buffer offset
buffer length position

position null
bytesRead buffer

fs.open fs.read
var fs = require('fs');
fs.open('content.txt', 'r', function(err, fd) {
if (err) {
console.error(err);
return;
}
var buf = new Buffer(8);
fs.read(fd, buf, 0, 8, null, function(err, bytesRead, buffer) {
if (err) {
console.error(err);
return;
}
console.log('bytesRead: ' + bytesRead);
console.log(buffer);
})
});

bytesRead: 8
<Buffer 54 65 78 74 20 e6 96 87>

4-1fs
4-1

fs

fs.open(path,flags, [mode], [callback(err,


fd)])

fs.openSync(path, flags, [mode])

fs.close(fd, [callback(err)])

fs.closeSync(fd)

4.4 fs

69

fs.read(fd,buffer,offset,length,position,
[callback(err, bytesRead, buffer)])

fs.readSync(fd, buffer, offset,


length, position)

fs.write(fd,buffer,offset,length,position,
[callback(err, bytesWritten, buffer)])

fs.writeSync(fd, buffer, offset,


length, position)

fs.readFile(filename,[encoding],[callba
ck(err, data)])

fs.readFileSync(filename,
[encoding])

fs.writeFile(filename,
[callback(err)])

fs.writeFileSync(filename, data,
[encoding])

fs.unlink(path, [callback(err)])

fs.mkdir(path, [mode], [callback(err)])

fs.mkdirSync(path, [mode])

fs.rmdir(path, [callback(err)])

fs.rmdirSync(path)

fs.readdir(path, [callback(err, files)])

fs.readdirSync(path)

fs.realpath(path, [callback(err,
resolvedPath)])

fs.realpathSync(path)

fs.rename(path1, path2, [callback(err)])

fs.renameSync(path1, path2)

fs.truncate(fd, len, [callback(err)])

fs.truncateSync(fd, len)

fs.chown(path, uid, gid, [callback(err)])

fs.chownSync(path, uid, gid)

fs.fchown(fd, uid, gid, [callback(err)])

fs.fchownSync(fd, uid, gid)

fs.lchown(path, uid, gid, [callback(err)])

fs.lchownSync(path, uid, gid)

fs.chmod(path, mode, [callback(err)])

fs.chmodSync(path, mode)

fs.fchmod(fd, mode, [callback(err)])

fs.fchmodSync(fd, mode)

fs.lchmod(path, mode, [callback(err)])

fs.lchmodSync(path, mode)

fs.stat(path, [callback(err, stats)])

fs.statSync(path)

fs.fstat(fd, [callback(err, stats)])

fs.fstatSync(fd)

fs.lstat(path, [callback(err, stats)])

fs.lstatSync(path)

fs.link(srcpath, dstpath, [callback(err)])

fs.linkSync(srcpath, dstpath)

fs.symlink(linkdata, path, [type],


[callback(err)])

fs.symlinkSync(linkdata, path,
[type])

fs.readlink(path, [callback(err,
linkString)])

fs.readlinkSync(path)

fs.utimes(path, atime, mtime, [callback


(err)])

fs.utimesSync(path, atime, mtime)

fs.futimes(fd, atime, mtime, [callback


(err)])

fs.futimesSync(fd, atime, mtime)

fs.fsync(fd, [callback(err)])

fs.fsyncSync(fd)

data,[encoding],

fs.unlinkSync(path)

10

70

4.5

Node.js

HTTP
Node.js http HTTP

HTTP http.Server HTTP Node.js C++


JavaScript http.request
HTTP HTTP Pingback

4.5.1 HTTP
http.Server http HTTP Node.js HTTP

http.Server
API

3.1.3 http
//app.js
var http = require('http');
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<h1>Node.js</h1>');
res.end('<p>Hello World</p>');
}).listen(3000);
console.log("HTTP server is listening at port 3000.");

http.createServer http.Server
HTTP req
res res 200

'Content-Type': 'text/html' '<h1>Node.js</h1>' res.end

listen 3000
1. http.Server
http.Server HTTP
HTTP
EventEmitter

Pingback WordPress
Pingback

4.5

HTTP

71

request req res

http.ServerRequest http.ServerResponse

connection TCP socket

net.Socket connection request

Keep-Alive

close

checkContinueupgradeclientError
HTTP
request http

http.createServer([requestListener]) HTTP
requestListener request

//httpserver.js
var http = require('http');

5
var server = new http.Server();
server.on('request', function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<h1>Node.js</h1>');
res.end('<p>Hello World</p>');

});
server.listen(3000);
console.log("HTTP server is listening at port 3000.");

2. http.ServerRequest
http.ServerRequest HTTP
http.Server request request req
ServerRequest 4-2

HTTP Request HeaderRequset Body

http.ServerRequest 3

data chunk

10

72

Node.js

end
close end

close
4-2

ServerRequest

complete

httpVersion

HTTP 1.0 1.1

method

HTTP GETPOSTPUTDELETE

url

/static/image/x.jpg /user?name=byvoid

headers

HTTP

trailers

HTTP

connection

HTTP net.Socket

socket

connection

client

client

3. GET
http.ServerRequest PHP $_GET
$_POST GET

URL ? GET
Node.js url parse
//httpserverrequestget.js
var http = require('http');
var url = require('url');
var util = require('util');
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(util.inspect(url.parse(req.url, true)));
}).listen(3000);

http://127.0.0.1:3000/user?name=byvoid&email=byvoid@byvoid.com

{ search: '?name=byvoid&email=byvoid@byvoid.com',
query: { name: 'byvoid', email: 'byvoid@byvoid.com' },
pathname: '/user',

4.5

HTTP

73

path: '/user?name=byvoid&email=byvoid@byvoid.com',
href: '/user?name=byvoid&email=byvoid@byvoid.com' }

url.parse path query GET


pathname
4. POST
HTTP 1.1 8 GET POST

GET POST
http.ServerRequest

POST

Node.js

//httpserverrequestpost.js
var http = require('http');
var querystring = require('querystring');
var util = require('util');

http.createServer(function(req, res) {
var post = '';
req.on('data', function(chunk) {
post += chunk;
});
req.on('end', function() {
post = querystring.parse(post);
res.end(util.inspect(post));
});

}).listen(3000);

post
req data

post end querystring.parse post


POST

9
POST

url http://nodejs.org/api/url.html

10

74

Node.js

5. http.ServerResponse
http.ServerResponse

http.Server request
response res
http.ServerResponse

response.writeHead(statusCode, [headers])

statusCode HTTP 200


404 headers

response.write(data, [encoding])data

Buffer data
encoding utf-8 response.end
response.write
response.end([data], [encoding])


response.write

4.5.2 HTTP
http http.request http.get HTTP

http.request(options, callback) HTTP option

callback option

host IP

port 80

method GET

path /
QueryString

/search?query=byvoid

headers

callback http.ClientResponse
http.request http.ClientRequest

4.5

HTTP

http.request POST

75

//httprequest.js
var http = require('http');
var querystring = require('querystring');
var contents = querystring.stringify({
name: 'byvoid',
email: 'byvoid@byvoid.com',
address: 'Zijing 2#, Tsinghua University',
});
var options = {
host: 'www.byvoid.com',
path: '/application/node/post.php',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length' : contents.length
}
};
var req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (data) {
console.log(data);
});
});
req.write(contents);
req.end();

array(3) {
["name"]=>
string(6) "byvoid"
["email"]=>
string(17) "byvoid@byvoid.com"
["address"]=>
string(30) "Zijing 2#, Tsinghua University"
}

req.end()

10

76

Node.js

http.get(options, callback) http

GEThttp.get http.request http.get


GET req.end()
//httpget.js
var http = require('http');
http.get({host: 'www.byvoid.com'}, function(res) {
res.setEncoding('utf8');
res.on('data', function (data) {
console.log(data);
});
});

1. http.ClientRequest
http.ClientRequest http.request http.get
HTTP response http.request
http.get

//httpresponse.js
var http = require('http');
var req = http.get({host: 'www.byvoid.com'});
req.on('response', function(res) {
res.setEncoding('utf8');
res.on('data', function (data) {
console.log(data);
});
});

http.ClientRequest http.ServerResponse write end

POSTPUT end
http.ClientRequest
request.abort()
request.setTimeout(timeout, [callback])timeout

callback
request.setNoDelay([noDelay])request.setSocketKeepAlive
([enable], [initialDelay]) Node.js

4.6

77

2. http.ClientResponse
http.ClientResponse http.ServerRequest dataend

close data
chunk
http.ClientResponse 4-3

4-3 ClientResponse

statusCode

HTTP 200404500

httpVersion

HTTP 1.0 1.1

headers

HTTP

trailers

HTTP

http.ClientResponse
response.setEncoding([encoding]) data

encoding null Buffer


utf8

response.pause()
response.resume()

4.6

Node.js Manual & Documentation: http://nodejs.org/api/index.html


Understanding process.nextTick(): http://howtonode.org/understanding- process-

next-tick
Node.js: http://www.grati.org/?p=318

10

5.1

79

Node.jsWeb

10

80

5 Node.js Web

Node.js

Express MVC ejs MongoDB

www.byvoid.com/project/node

5.1

Node.js Node.js PHP

PerlASPJSP HTML
HTML
10001000 HTML
1000 HTML
Perl CGI Perl HTML HTTP
Perl 20 90
HTML
2000 ASPPHPJSP
CGI HTML
2002
MVC
Ruby on RailsDjangoZend Framework MVC
MVC Model-View-Controller
20 70 Smalltalk


HTML

PHPASPJSP 5-1 Web

C++Perl
ASP <% %> PHP <?php ?>

5.1

81

5-1 Web

MVC

HTML

SQL

HTTP

HTTP

3
CGI

Node.js Perl C++ CGI HTTP

HTTP ApacheNginxIIS
Node.js Node.js http C++
5-1

5-1

Node.js PHP

Node.js PHP
$_REQUEST POST GET HTTP

http://example.com/hello/world.php /hello/world.php
PHP Rewrite

Node.js Apache Nginx

10

82

5 Node.js Web

HTTP HTTP
HTTP CGI
HTTP Node.js

5.1.1 http
Node.js HTTP
POST
<form method="post" action="http://localhost:3000/">
<input type="text" name="title" />
<textarea name="text"></textarea>
<input type="submit" />
</form>

title text POST


http://localhost:3000/
PHP index.php
echo $_POST['title'];
echo $_POST['text'];

3.5.1 http
var http = require('http');
var querystring = require('querystring');
var server = http.createServer(function(req, res) {
var post = '';
req.on('data', function(chunk) {
post += chunk;
});
req.on('end', function() {
post = querystring.parse(post);
res.write(post.title);
res.write(post.text);
res.end();
});
}).listen(3000);

HTTP 200 200


HTTP HTTP

5.1

83

PHP Node.jsNode.js
http
req POST end
POST
PHP
PHP Node.js http
HTTP
HTTP Node.js Web
Node.js

Node.js http Web


http HTTP HTTP
HTTP
POST Cookie

5.1.2 Express

npm Web
Express Node.js
Web

Express http://expressjs.com/ http




CSRF

Express Rails Django


ORM Object Relation Model Web

10

84

5 Node.js Web

HTTP

Express
var express = require('express');
var app = express.createServer();
app.use(express.bodyParser());
app.all('/', function(req, res) {
res.send(req.body.title + req.body.text);
});
app.listen(3000);

req express.bodyParser()
req.body POST

5.2

Web Express

5.2.1 Express
Express

3.3.4 Express
Express Quick Start

Express
$ npm install -g express

express
express --help
Usage: express [options] [path]
Options:
-s, --sessions
-t, --template <engine>

add session support


add template <engine> support (jade|ejs). default=jade

5.2
-c, --css <engine>
-v, --version
-h, --help

85

add stylesheet <engine> support (stylus). default=plain css


output framework version
output help information

Express Jadeejs
ejs CSS

5.2.2

express -t ejs microblog

microblog
create
create
create
create
create
create
create
create
create
create
create
create
create

:
:
:
:
:
:
:
:
:
:
:
:
:

microblog
microblog/package.json
microblog/app.js
microblog/public
microblog/public/javascripts
microblog/public/images
microblog/public/stylesheets
microblog/public/stylesheets/style.css
microblog/routes
microblog/routes/index.js
microblog/views
microblog/views/layout.ejs
microblog/views/index.ejs

dont forget to install dependencies:


$ cd microblog && npm install

npm install
ejs@0.6.1 ./node_modules/ejs
express@2.5.8 ./node_modules/express
-- qs@0.4.2
-- mime@1.2.4
-- mkdirp@0.3.0
-- connect@1.8.5

ejs express package.json

ejsEmbedded JavaScript ASPPHP Express


jade HTML

10

86

5 Node.js Web
{
"name": "microblog"
, "version": "0.0.1"
, "private": true
, "dependencies": {
"express": "2.5.8"
, "ejs": ">= 0.0.1"
}
}

dependencies express ejs npm install


package.json

5.2.3
Express Node.js node
app.js Express server listening on port 3000 in development mode

http://localhost:3000 Welcome
to Express 5-2

5-2

Express

Ctrl + C

supervisor 3.1.3

5.2

87

development mode
6.3
Node.js

2
5.2.4
Express package.json
JavaScript app.js routes/index.js ejs index.ejs layout.ejs 3
style.css
1. app.js
app.js

/**
* Module dependencies.
*/
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', 'ejs');
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);
console.log("Express server listening on port %d in %s mode", app.address().port,
app.settings.env);

10

88

5 Node.js Web

Express

Express npm
require routes ./routes/index.js

MVC express.createServer()

app.configure
app.configure
app.set Express keyvalue

basepath res.redirect()
views
view engine
view options
view cache
case sensitive routes
strict routing /

jsonp callback JSONP

Express connect app.use app.configure


5bodyParsermethodOverriderouterstatic errorHandler
bodyParser POST methodOverride

HTTP router static


errorHandler
app.get('/', routes.index); /

routes.index
app.listen(3000); 3000
2. routes/index.js
routes/index.js
/*
* GET home page.
*/
exports.index = function(req, res) {

PUTDELETEHTTP

5.3

89

res.render('index', { title: 'Express' });


};

app.js app.get('/', routes.index); / exports.index


res.render('index', { title: 'Express' })
index

title: 'Express'
3. index.ejs
index.ejs routes/index.js

<h1><%= title %></h1>


<p>Welcome to <%= title %></p>

HTML <%= title %>


res.render

4. layout.ejs
layout.ejs <%- body %>

<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<%- body %>
</body>
</html>

5.3

Express
Express

5.3.1
app.js

10

90

5 Node.js Web

http://localhost:3000
GET / HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.142
Safari/535.19
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: UTF-8,*;q=0.5

HTTP HTTP app


app.js app.get('/', routes.index)
/ GET routes.index routes.index
res.render('index', { title: 'Express' }) index title
HTML
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 202
Connection: keep-alive
<!DOCTYPE html>
<html>
<head>
<title>Express</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1>Express</h1>
<p>Welcome to Express</p>
</body>
</html>

/stylesheets/style.css
app.js /stylesheets/style.css app
app.use(express.static(__dirname + '/public'))

/stylesheets/style.css app.js public/stylesheets/style.css

5.3

91

HTTP/1.1 200 OK
X-Powered-By: Express
Date: Mon, 02 Apr 2012 15:56:55 GMT
Cache-Control: public, max-age=0
Last-Modified: Mon, 12 Mar 2012 12:49:50 GMT
ETag: "110-1331556590000"
Content-Type: text/css; charset=UTF-8
Accept-Ranges: bytes
Content-Length: 110
Connection: keep-alive
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}

a {
color: #00B7FF;
}

Express 5-3

9
5-3

Express

MVC

10

92

5 Node.js Web

HTML

5.3.2
http://localhost:3000/abc
404 Not Found 5-4

5-4

/abc public
Express404 Not Found

/hello
app.js app.get('/', routes.index)
app.get('/hello', routes.hello);

routes/index.js hello
/*
* GET home page.
*/
exports.index = function(req, res) {
res.render('index', { title: 'Express' });

5.3

93

};

exports.hello = function(req, res) {


res.send('The time is ' + new Date().toString());
};

app.js http://localhost:3000/hello5-5

6
5-5

/hello

app.get

req
res

5.3.3

Express
/user/[username]

app.get('/user/:username', function(req, res) {


res.send('user: ' + req.params.username);
});

10

94

5 Node.js Web

app.js http://localhost:3000/user/byvoid

user: byvoid

/user/:username \/user\/([^\/]+)\/?
req.params
JavaScript app.get(\/user\/([^\/]+)\/?,
callback)

req.params[0]req.params[1]

5.3.4 REST
Express REST RESTREST
Representational State Transfer HTTP
HTTP HTTP 8

GET
HEAD
POST
PUT
DELETE
TRACE
CONNECTHTTP/1.1
OPTIONSHTTP

GETPOSTPUT DELETE REST


4
GET
POST
PUT
DELETE

4 5-2

5.3

95

5-2 RESTHTTP

GET

POST

PUT

DELETE

Express HTTP
app.get GET

5-3 Express HTTP

5-3 Express HTTP

GET

app.get(path, callback)

POST

app.post(path, callback)

PUT

app.put(path, callback)

DELETE

app.delete(path, callback)

PATCH

app.patch(path, callback)

TRACE

app.trace(path, callback)

CONNECT

app.connect(path, callback)

OPTIONS

app.options(path, callback)

app.all(path, callback)

POST app.post(path, callback)


app.all

5.3.5
Express
app.all('/user/:username', function(req, res) {
res.send('all methods captured');
});
app.get('/user/:username', function(req, res) {
res.send('user: ' + req.params.username);
});

PATCH IETF RFC 5789 http://tools.ietf.org/html/rfc5789 HTTP

10

96

5 Node.js Web

Express

Express next
next()
app.all('/user/:username', function(req, res, next) {
console.log('all methods captured');
next();
});
app.get('/user/:username', function(req, res) {
res.send('user: ' + req.params.username);
});

http://localhost:3000/user/carbo all
methods captured user: carbo

console.log next()

GET PUT
next()
var users = {
'byvoid': {
name: 'Carbo',
website: 'http://www.byvoid.com'
}
};
app.all('/user/:username', function(req, res, next) {
//
if (users[req.params.username]) {
next();
} else {
next(new Error(req.params.username + ' does not exist.'));
}
});
app.get('/user/:username', function(req, res) {
//
res.send(JSON.stringify(users[req.params.username]));
});
app.put('/user/:username', function(req, res) {
//
res.send('Done');
});

5.4

97

app.all
next

5.4

Express MVC

ejs

5.4.1
Template Engine HTML
1996 PHP 2.0 PHP Personal Home Page Tools

Perl CGI HTML


PHP ASPJSP
HTML HTML

MVC
MVC
HTML

HTML
HTML

XSLT XML

HTML XSLT

MVC

10

98

5 Node.js Web

HTML
5-6 MVC

5-6

MVC

5.4.2
JavaScript ejs Embedded JavaScript
Express JavaScript
ejs

app.js
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');

ejs views routes/index.js


exports.index
res.render('index', { title: 'Express' });

res.render

views
index.ejs
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>

<%= title %>


Express res.render { title: 'Express' }

5.4

99

ejs 3
<% code %>JavaScript

<%= code %> HTML


<%- code %> HTML

5.4.3
Express
layout.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<%- body %>
</body>
</html>

layout.ejs
<%- body %>
HTML <head>

layout.ejs
app.js app.configure
app.set('view options', {
layout: false
});

layout
function(req, res) {
res.render('userlist', {
title: '',
layout: 'admin'
});
};

userlist admin.ejs

10

100

5 Node.js Web

5.4.4
Express partials

for app.js
app.get('/list', function(req, res) {
res.render('list', {
title: 'List',
items: [1991, 'byvoid', 'express', 'Node.js']
});
});

views list.ejs
<ul><%- partial('listitem', items) %></ul>

listitem.ejs
<li><%= listitem %></li>

http://localhost:3000/list
<!DOCTYPE html>
<html>
<head>
<title>List</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<ul><li>1991</li><li>byvoid</li><li>express</li><li>Node.js</li></ul>
</body>
</html>

partial

'listitem'

5.4.5
Express
partial

req res

5.4

101

app.helpers()
app.dynamicHelpers()

req res

var util = require('util');


app.helpers({
inspect: function(obj) {
return util.inspect(obj, true);
}
});
app.dynamicHelpers({
headers: function(req, res) {
return req.headers;
}
});

app.get('/helper', function(req, res) {


res.render('helper', {
title: 'Helpers'
});
});

helperejs

<%=inspect(headers)%>

http://localhost:3000/helper 5-7

5-7

10

102

5 Node.js Web

session

5.5

Express

5.5.1

5.5.2

/
/u/[user]
/post
/reg
/login
/logout

app.js Routes
app.get('/', routes.index);
app.get('/u/:user', routes.user);
app.post('/post', routes.post);

5.5

103

app.get('/reg', routes.reg);
app.post('/reg', routes.doReg);
app.get('/login', routes.login);
app.post('/login', routes.doLogin);
app.get('/logout', routes.logout);

/post/login /reg app.post /login

/reg app.get routes/index.js

exports.index = function(req, res) {


res.render('index', { title: 'Express' });
};
exports.user = function(req, res) {
};

exports.post = function(req, res) {


};
exports.reg = function(req, res) {
};

exports.doReg = function(req, res) {


};
exports.login = function(req, res) {
};

exports.doLogin = function(req, res) {


};
exports.logout = function(req, res) {
};

5.6session

5.5.3

10

104

5 Node.js Web

Twitter Twitter Bootstrap Twitter


Bootstrap Twitter Twitter
Web UI HTMLCSSJavaScript
Twitter Bootstrap
5-8 Twitter Bootstrap

5-8

Twitter Bootstrap

5.5.4 Bootstrap
Bootstrap http://twitter.github.com/bootstrap/
bootstrap.zip
css/bootstrap-responsive.css
css/bootstrap-responsive.min.css
css/bootstrap.css
css/bootstrap.min.css
img/glyphicons-halflings-white.png
img/glyphicons-halflings.png
js/bootstrap.js
js/bootstrap.min.js

5.5

105

JavaScript CSS
min img public bootstrap.css

bootstrap-responsive.css public/stylesheets bootstrap.js public/javascripts


http://jquery.com/ jquery.js public/javascripts
views/layout.ejs
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title><%= title %> - Microblog</title>
<link rel='stylesheet' href='/stylesheets/bootstrap.css' />
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
</style>
<link href="stylesheets/bootstrap-responsive.css" rel="stylesheet">
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="/">Microblog</a>
<div class="nav-collapse">
<ul class="nav">
<li class="active"><a href="/"></a></li>
<li><a href="/login"></a></li>
<li><a href="/reg"></a></li>
</ul>
</div>
</div>
</div>
</div>
<div id="container" class="container">
<%- body %>

10

106

5 Node.js Web

<hr />
<footer>
<p><a href="http://www.byvoid.com/" target="_blank">BYVoid</a> 2012</p>
</footer>
</div>
</body>
<script src="/javascripts/jquery.js"></script>
<script src="/javascripts/bootstrap.js"></script>
</html>

Bootstrap
container div
views/index.ejs
<div class="hero-unit">
<h1> Microblog</h1>
<p>Microblog Node.js </p>
<p>
<a class="btn btn-primary btn-large" href="/login"></a>
<a class="btn btn-large" href="/reg"></a>
</p>
</div>
<div class="row">
<div class="span4">
<h2>Carbo </h2>
<p> </p>
</div>
<div class="span4">
<h2>BYVoid </h2>
<p>
Open Chinese ConvertOpenCC

(libopencc)
</p>
</div>
<div class="span4">
<h2> </h2>
<p> / Rime Input Method Engine

http://code.google.com/p/rimeime/

</p>
</div>
</div>

5.6

107

5-9

5-9

Bootstrap

Bootstrap

5.6

Bootstrap

5.6.1
MongoDB NoSQL
MySQL

1. NoSQL
NoSQL

10

108

5 Node.js Web

tablerowfield

indexprimary key
unique key
foreign key

SQL
Structured Query Language SQL SQL
MySQLOracleMicrosoft SQL ServerPostgreSQLSQLite
NoSQL 1998 SQL
NoSQL Not Only SQL ACID
NoSQL SQL
SQL NoSQL SQL
NoSQL
2. MongoDB
MongoDB

MongoDB
{ "_id" : ObjectId( "4f7fe8432b4a1077a7c551e8" ),
"uid" : 2004,
"username" : "byvoid",
"net9" : { "nickname" : "BYVoid",
"surname" : "Kuo",
"givenname" : "Carbo",
"fullname" : "Carbo Kuo",
"emails" : [ "byvoid@byvoid.com", "byvoid.kcp@gmail.com" ],
"website" : "http://www.byvoid.com",
"address" : "Zijing 2#, Tsinghua University" }
}

uid username _id


ObjectIdnet9
JSONMongoDB JSON JavaScript

ACID transactionatomicityconsistency
isolationdurability
MongoDB BSON Binary JSON JSON

5.6

109

Mongodb

MongoDB SQL

3.
MongoDB

http://www.mongodb.org/
Node.js MongoDB package.json
dependencies

{
"name": "microblog"
, "version": "0.0.1"
, "private": true
, "dependencies": {
"express": "2.5.8"
, "ejs": ">= 0.0.1"
, "mongodb": ">= 0.9.9"
}

npm install settings.js


microblog
Settings.js
module.exports = {
cookieSecret: 'microblogbyvoid',
db: 'microblog',
host: 'localhost',
};

db host cookieSecret Cookie

models db.js
var
var
var
var

settings = require('../settings');
Db = require('mongodb').Db;
Connection = require('mongodb').Connection;
Server = require('mongodb').Server;

module.exports = new Db(settings.db, new Server(settings.host, Connection.DEFAULT_


PORT, {}));

10

110

5 Node.js Web

module.exports

5.6.2

FTPTelnet
HTTP

HTTP Cookie Cookie


Cookie
HTTP

Cookie

PHP
Express
MongoDB
connect-mongo package.json
{
"name": "microblog"
, "version": "0.0.1"
, "private": true
, "dependencies": {
"express": "2.5.8"
, "ejs": ">= 0.0.1"
, "connect-mongo": ">= 0.1.7"
, "mongodb": ">= 0.9.9"
}
}

npm install app.js


var MongoStore = require('connect-mongo');
var settings = require('../settings');

5.6

111

app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({
secret: settings.cookieSecret,
store: new MongoStore({
db: settings.db
})
}));
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});

express.cookieParser() Cookie express.session()

store MongoStore

req.session

5.6.3

1.
views/reg.ejs
<form class="form-horizontal" method="post">
<fieldset>
<legend></legend>
<div class="control-group">
<label class="control-label" for="username"></label>
<div class="controls">
<input type="text" class="input-xlarge" id="username" name="username">
<p class="help-block"></p>
</div>
</div>
<div class="control-group">
<label class="control-label" for="password"></label>
<div class="controls">
<input type="password" class="input-xlarge" id="password" name="password">
</div>

10

112

5 Node.js Web

</div>
<div class="control-group">
<label class="control-label" for="password-repeat"></label>
<div class="controls">
<input type="password" class="input-xlarge" id="password-repeat"
name="password-repeat">
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary"></button>
</div>
</fieldset>
</form>

3 usernamepassword password-repeat
POST
app.js
app.js app.configure
app.use(express.router(routes)) app.use(app.router)
app.configure(function(){
app.set('views', --dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({
secret: settings.cookieSecret,
store: new MongoStore({
db: settings.db
})
}));
app.use(express.router(routes));
app.use(express.static(--dirname + '/public'));
});

routes/index.js
module.exports = function(app) {
app.get('/', function(req, res) {
res.render('index', {
title: ''
});
});
app.get('/reg', function(req, res) {
res.render('reg', {

5.6

113

title: '',
});
});

};

app.js http://localhost:3000/reg5-10

7
5-10

2.

POST routes/

index.js /reg POST


app.post('/reg', function(req, res) {
//
if (req.body['password-repeat'] != req.body['password']) {
req.flash('error', '');
return res.redirect('/reg');
}

10

114

5 Node.js Web
//
var md5 = crypto.createHash('md5');
var password = md5.update(req.body.password).digest('base64');
var newUser = new User({
name: req.body.username,
password: password,
});

//
User.get(newUser.name, function(err, user) {
if (user)
err = 'Username already exists.';
if (err) {
req.flash('error', err);
return res.redirect('/reg');
}
//
newUser.save(function(err) {
if (err) {
req.flash('error', err);
return res.redirect('/reg');
}
req.session.user = newUser;
req.flash('success', '');
res.redirect('/');
});
});
});

req.body POST

password req.body['password']
req.flash Express

res.redirect 303 See Other

crypto Node.js

var crypto = require('crypto')

User

var User = require('../models/user.js')

5.6

115

User.get

User.save

req.session.user = newUser

3.
User User MVC

User

models user.js
var mongodb = require('./db');
function User(user) {
this.name = user.name;
this.password = user.password;
};
module.exports = User;
User.prototype.save = function save(callback) {
// Mongodb
var user = {
name: this.name,
password: this.password,
};
mongodb.open(function(err, db) {
if (err) {
return callback(err);
}
// users
db.collection('users', function(err, collection) {
if (err) {
mongodb.close();
return callback(err);
}
// name
collection.ensureIndex('name', {unique: true});
// user
collection.insert(user, {safe: true}, function(err, user) {
mongodb.close();
callback(err, user);
});
});

10

116

5 Node.js Web
});

};
User.get = function get(username, callback) {
mongodb.open(function(err, db) {
if (err) {
return callback(err);
}
// users
db.collection('users', function(err, collection) {
if (err) {
mongodb.close();
return callback(err);
}
// name username
collection.findOne({name: username}, function(err, doc) {
mongodb.close();
if (doc) {
// User
var user = new User(doc);
callback(err, user);
} else {
callback(err, null);
}
});
});
});
};

User.prototype.save User.get

4.

app.js
app.dynamicHelpers({
user: function(req, res) {
return req.session.user;
},
error: function(req, res) {
var err = req.flash('error');

5.6

117

if (err.length)
return err;

else
return null;
},
success: function(req, res) {

var succ = req.flash('success');


if (succ.length)
return succ;
else
return null;

},
});

layout.ejs

<ul class="nav">
<li class="active"><a href="/"></a></li>
<% if (!user) { %>
<li><a href="/login"></a></li>
<li><a href="/reg"></a></li>

<% } else { %>


<li><a href="/logout"></a></li>
<% } %>
</ul>

container <%- body %>

<% if (success) { %>


<div class="alert alert-success">

<%= success %>


</div>
<% } %>
<% if (error) { %>

<div class="alert alert-error">


<%= error %>
</div>
<% } %>

5-115-12

10

118

5 Node.js Web

5-11

5-12

5.6

119

5.

routes/index.js
app.get('/login', function(req, res) {
res.render('login', {
title: '',
});
});
app.post('/login', function(req, res) {
//
var md5 = crypto.createHash('md5');
var password = md5.update(req.body.password).digest('base64');

User.get(req.body.username, function(err, user) {


if (!user) {
req.flash('error', '');
return res.redirect('/login');
}
if (user.password != password) {
req.flash('error', '');
return res.redirect('/login');
}
req.session.user = user;
req.flash('success', '');
res.redirect('/');
});
});

app.get('/logout', function(req, res) {


req.session.user = null;
req.flash('success', '');
res.redirect('/');
});

req.session.user

views/login.ejs
<form class="form-horizontal" method="post">
<fieldset>
<legend></legend>
<div class="control-group">
<label class="control-label" for="username"></label>

10

120

5 Node.js Web

<div class="controls">
<input type="text" class="input-xlarge" id="username" name="username">
</div>
</div>
<div class="control-group">
<label class="control-label" for="password"></label>
<div class="controls">
<input type="password" class="input-xlarge" id="password" name="password">
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary"></button>
</div>
</fieldset>
</form>

http://localhost:3000/login5-13

5-13

5.6.4

5.6

121

DRY
5.3.5 next()

routes/index.js

var crypto = require('crypto');


var User = require('../models/user.js');
module.exports = function(app) {
app.get('/', function(req, res) {
res.render('index', {
title: ''
});
});

5
app.get('/reg', checkNotLogin);
app.get('/reg', function(req, res) {
res.render('reg', {
title: '',
});
});
app.post('/reg', checkNotLogin);
app.post('/reg', function(req, res) {
//
if (req.body['password-repeat'] != req.body['password']) {
req.flash('error', '');
return res.redirect('/reg');
}
//
var md5 = crypto.createHash('md5');
var password = md5.update(req.body.password).digest('base64');
var newUser = new User({
name: req.body.username,
password: password,
});

DRY Dont Repeat Yourself Once And Only Once

10

122

5 Node.js Web

//
User.get(newUser.name, function(err, user) {
if (user)
err = 'Username already exists.';
if (err) {
req.flash('error', err);
return res.redirect('/reg');
}
//
newUser.save(function(err) {
if (err) {
req.flash('error', err);
return res.redirect('/reg');
}
req.session.user = newUser;
req.flash('success', '');
res.redirect('/');
});
});
});
app.get('/login', checkNotLogin);
app.get('/login', function(req, res) {
res.render('login', {
title: '',
});
});
app.post('/login', checkNotLogin);
app.post('/login', function(req, res) {
//
var md5 = crypto.createHash('md5');
var password = md5.update(req.body.password).digest('base64');
User.get(req.body.username, function(err, user) {
if (!user) {
req.flash('error', '');
return res.redirect('/login');
}
if (user.password != password) {
req.flash('error', '');
return res.redirect('/login');
}
req.session.user = user;
req.flash('success', '');
res.redirect('/');
});
});

5.7

123

app.get('/logout', checkLogin);
app.get('/logout', function(req, res) {
req.session.user = null;
req.flash('success', '');
res.redirect('/');
});

};
function checkLogin(req, res, next) {
if (!req.session.user) {
req.flash('error', '');
return res.redirect('/login');
}
next();
}

4
function checkNotLogin(req, res, next) {
if (req.session.user) {
req.flash('error', '');
return res.redirect('/');
}
next();
}

5.7

5.7.1
Post
User Post.get Post.prototype.savePost.get

Post.prototype.save
Post
models/post.js

var mongodb = require('./db');


function Post(username, post, time) {
this.user = username;
this.post = post;

10

124

5 Node.js Web
if (time) {
this.time = time;
} else {
this.time = new Date();
}

};
module.exports = Post;
Post.prototype.save = function save(callback) {
// Mongodb
var post = {
user: this.user,
post: this.post,
time: this.time,
};
mongodb.open(function(err, db) {
if (err) {
return callback(err);
}
// posts
db.collection('posts', function(err, collection) {
if (err) {
mongodb.close();
return callback(err);
}
// user
collection.ensureIndex('user');
// post
collection.insert(post, {safe: true}, function(err, post) {
mongodb.close();
callback(err, post);
});
});
});
};
Post.get = function get(username, callback) {
mongodb.open(function(err, db) {
if (err) {
return callback(err);
}
// posts
db.collection('posts', function(err, collection) {
if (err) {
mongodb.close();
return callback(err);
}

5.7

125

// user username username null


var query = {};
if (username) {
query.user = username;
}
collection.find(query).sort({time: -1}).toArray(function(err, docs) {
mongodb.close();
if (err) {
callback(err, null);
}
// posts Post
var posts = [];
docs.forEach(function(doc, index) {
var post = new Post(doc.user, doc.post, doc.time);
posts.push(post);
});
callback(null, posts);
});
});
});
};

5.7.2
POST /post

routes/index.js
app.post('/post', checkLogin);
app.post('/post', function(req, res) {
var currentUser = req.session.user;
var post = new Post(currentUser.name, req.body.post);
post.save(function(err) {
if (err) {
req.flash('error', err);
return res.redirect('/');
}
req.flash('success', '');
res.redirect('/u/' + currentUser.name);
});
});

req.session.user req.body.post
Post save()

10

126

5 Node.js Web

5.7.3
routes/index.js
app.get('/u/:user', function(req, res) {
User.get(req.params.user, function(err, user) {
if (!user) {
req.flash('error', '');
return res.redirect('/');
}
Post.get(user.name, function(err, posts) {
if (err) {
req.flash('error', err);
return res.redirect('/');
}
res.render('user', {
title: user.name,
posts: posts,
});
});
});
});

posts user views/user.ejs


<% if (user) { %>
<%- partial('say') %>
<% } %>
<%- partial('posts') %>

DRY say.ejs posts.ejssay.ejs

<form method="post" action="/post" class="well form-inline center" style="text-align:


center;">
<input type="text" class="span8" name="post">
<button type="submit" class="btn btn-success"><i class="icon-comment icon-white">
</i> </button>
</form>

posts.ejs posts
<% posts.forEach(function(post, index) {
if (index % 3 == 0) { %>
<div class="row">
<%} %>
<div class="span4">

5.7

127

<h2><a href="/u/<%= post.user %>"><%= post.user %></a> </h2>


<p><small><%= post.time %></small></p>
<p><%= post.post %></p>
</div>
<% if (index % 3 == 2) { %>
</div><!-- end row -->
<% } %>
<%}) %>
<% if (posts.length % 3 != 0) { %>
</div><!-- end row -->
<%} %>

5-14

5-14

5.7.4

routes/index.js
app.get('/', function(req, res) {
Post.get(null, function(err, posts) {
if (err) {

10

128

5 Node.js Web

posts = [];
}
res.render('index', {
title: '',
posts: posts,
});
});
});

posts
index.ejs
<% if (!user) { %>
<div class="hero-unit">
<h1> Microblog</h1>
<p>Microblog Node.js </p>
<p>
<a class="btn btn-primary btn-large" href="/login"></a>
<a class="btn btn-large" href="/reg"></a>
</p>
</div>
<% } else { %>
<%- partial('say') %>
<% } %>
<%- partial('posts') %>

5-155-16

5-15

5.8

129

4
5-16

5.7.5

OAuth HTML

Node.js https://github.com/BYVoid/
microblog Microblog

5.8

Node.jsWeb MVC: http://club.cnodejs.org/topic/4f16442

ccae1f4aa27001135

10

130

5 Node.js Web

A HTTP Proxy Server in 20 Lines of node.js Code: http://www.catonmat.net/http-proxy-

in-nodejs/
Node.js Recommended Third-party Modules: http://nodejs.org/api/appendix_1.html
Express Guide: http://expressjs.com/guide.html
EJSEmbedded JavaScript: http://embeddedjs.com/
Jade: http://jade-lang.com/
JSON-P: http://www.json-p.org/
Connect: http://www.senchalabs.org/connect/
REST: http://www.infoq.com/cn/articles/rest-introduction
HTTP Verbs: POSTPUT PATCH : http://ihower.tw/blog/archives/6483
Template engine (Web): http://en.wikipedia.org/wiki/Template_engine_(Web)
Bootstrap: http://twitter.github.com/bootstrap/
MongoDB Manual: http://www.mongodb.org/display/DOCS/Manual

6.1

131

Node.js

10

132

Node.js



Node.js
Node.js

6.1

Node.js require

Node.js

6.1.1
Node.js
Node.js API fshttpnetvm Node.js
require
require('fs')

Node.js
JavaScript JSON
C/C++ npm
Node.js .js.json .node
.js JavaScript .json JSON .node C/C++
6-1 Node.js
6-1 Node.js

JavaScript

.js

JSON

.json

C/C++

.node

6.1.2
node_modules
require / require
('/home/byvoid/module') /home/byvoid/module.js

6.1

133

/home/byvoid/module.json /home/byvoid/module.node
require ./ ../

require('./hello')
hello.js

6.1.3 node_modules

require /
./ ../
node_modules npm

npm install expressnode_modules


6-1

6-1

node_modules

node_modules require('express')
require('./node_modules/express')Node.js

node_modules
require

node_modules
node_modules
/home/byvoid/develop/foo.js require('bar.js')

10

134

Node.js

Node.js
/home/byvoid/develop/node_modules/bar.js
/home/byvoid/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js

|- project
|- app.js
|- models
|- ...
|- views
|- ...
|- controllers
|- index_controller.js
|- error_controller.js
|- ...
|- node_modules
|- express

project app.js require('express')


controllers index_controller.js require('express')
node_modules express

6.1.4
Node.js Node.js
Node.js
require()
require('express') require('./node_modules/express')

6.1.5
require(some_module)
(1) some_module
(2) some_module /

./ ../ some_module
(3) current_dir current_dir/node_modules/some_module

6.2

135

current_dir

6.2

I/O

6.2.1

Node.js

//forloop.js
var fs = require('fs');
var files = ['a.txt', 'b.txt', 'c.txt'];
for (var i = 0; i < files.length; i++) {
fs.readFile(files[i], 'utf-8', function(err, contents) {
console.log(files[i] + ': ' + contents);
});
}

a.txtb.txtc.txt
AAABBB CCC
a.txt: AAA
b.txt: BBB
c.txt: CCC

undefined: AAA
undefined: BBB
undefined: CCC

contents

files[i] undefined
files[i]
filesi files[i]

10

136

Node.js

//forloopi.js
var fs = require('fs');
var files = ['a.txt', 'b.txt', 'c.txt'];
for (var i = 0; i < files.length; i++) {
fs.readFile(files[i], 'utf-8', function(err, contents) {
console.log(files);
console.log(i);
console.log(files[i]);
});
}

[ 'a.txt', 'b.txt', 'c.txt' ]


3
undefined
[ 'a.txt', 'b.txt', 'c.txt' ]
3
undefined
[ 'a.txt', 'b.txt', 'c.txt' ]
3
undefined

i 3 files
files[i] undefined for
for (var i = 0; i < files.length; i++) i
files.length i 3 fs.readFile

i files[i] fs.readFile

3
i
JavaScript
//forloopclosure.js
var fs = require('fs');
var files = ['a.txt', 'b.txt', 'c.txt'];
for (var i = 0; i < files.length; i++) {
(function(i) {
fs.readFile(files[i], 'utf-8', function(err, contents) {
console.log(files[i] + ': ' + contents);
});
})(i);
}

6.2

137

for i

fs.readFile i

forEach
//callbackforeach.js
var fs = require('fs');
var files = ['a.txt', 'b.txt', 'c.txt'];
files.forEach(function(filename) {
fs.readFile(filename, 'utf-8', function(err, contents) {
console.log(filename + ': ' + contents);
});
});

6.2.2

Node.js

async
async.seriesasync.parallelasync.waterfall

streamlinejsjscex

JavaScript JavaScript

eventproxy

10

138

Node.js

Node.jshttp://club.cnodejs.org/

6.3

Node.js
5Expressnode app.js

bug
Node.js

Node.jsCPU

IP

PHPRailsNode.js
80

6.3.1
5Express

6.3

Node.js

139

NODE_ENV NODE_ENV=production

node app.js
Express server listening on port 3000 in production mode

IP

Express stream
app.js
var fs = require('fs');
var accessLogfile = fs.createWriteStream('access.log', {flags: 'a'});
var errorLogfile = fs.createWriteStream('error.log', {flags: 'a'});

app.configure
app.use(express.logger({stream: accessLogfile}));

app.configure('production', function(){
app.error(function (err, req, res, next) {
var meta = '[' + new Date() + '] ' + req.url + '\n';
errorLogfile.write(meta + err.stack + '\n');
next();
});
});

app.error

http://127.0.0.1:3000/app.js
access.log
127.0.0.1 - - [Thu, 5 Apr 2012 15:29:28 GMT] "GET / HTTP/1.1" 200 3389 "-" "Mozilla/5.0
(Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.19 (KHTML, like Gecko)
Chrome/18.0.1025.162 Safari/535.19"
127.0.0.1 - - [Thu, 5 Apr 2012 15:29:28 GMT] "GET /stylesheets/bootstrap-responsive.css
HTTP/1.1" 304 - "http://127.0.0.1:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3)
AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19"
127.0.0.1 - - [Thu, 5 Apr 2012 15:29:28 GMT] "GET /javascripts/jquery.js HTTP/1.1" 304
- "http://127.0.0.1:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3)
AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19"
127.0.0.1 - - [Thu, 5 Apr 2012 15:29:28 GMT] "GET /javascripts/bootstrap.js HTTP/1.1"
304 - "http://127.0.0.1:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3)
AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19"

10

140

Node.js

127.0.0.1 - - [Thu, 5 Apr 2012 15:29:28 GMT] "GET /stylesheets/bootstrap.css HTTP/1.1"


304 - "http://127.0.0.1:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3)
AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19"
127.0.0.1 - - [Thu, 5 Apr 2012 15:29:28 GMT] "GET /favicon.ico HTTP/1.1" 404 - "-"
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.19 (KHTML, like Gecko)
Chrome/18.0.1025.162 Safari/535.19"

routes/index.js /
throw new Error('An error for test purposes.');

http://127.0.0.1:3000/ error.log
[Thu Apr 5 2012 23:33:21 GMT+0800 (CST)] /
Error: An error for test purposes.
at Object.<anonymous> (/byvoid/microblog/routes/index.js:7:11)
at nextMiddleware (/byvoid/microblog/node_modules/express/node_modules/connect/
lib/middleware/router.js:175:25)
at param (/byvoid/microblog/node_modules/express/node_modules/connect/lib/
middleware/router.js:183:16)
at pass (/byvoid/microblog/node_modules/express/node_modules/connect/lib/
middleware/router.js:191:10)
at Object.router [as handle] (/byvoid/microblog/node_modules/express/
node_modules/connect/lib/middleware/router.js:197:6)
at next (/byvoid/microblog/node_modules/express/node_modules/connect/lib/
http.js:203:15)
at /byvoid/microblog/node_modules/express/node_modules/connect/lib/middleware/
session.js:323:9
at /byvoid/microblog/node_modules/express/node_modules/connect/lib/middleware/
session.js:342:9
at /byvoid/microblog/node_modules/connect-mongo/lib/connect-mongo.js:151:15
at /byvoid/microblog/node_modules/connect-mongo/node_modules/mongodb/lib/
mongodb/collection.js:885:34

6.3.2 cluster
0.6 Node.js clustercluster
Node.js
child_process cluster

app.jsapp.jsapp.listen
(3000);
if (!module.parent) {
app.listen(3000);
console.log("Express server listening on port %d in %s mode", app.address().port,
app.settings.env);
}

6.3

Node.js

141

node app.jsrequire('./app')
listen()
cluster app.jscluster.js

var cluster = require('cluster');


var os = require('os');
// CPU
var numCPUs = os.cpus().length;
var workers = {};
if (cluster.isMaster) {
//
cluster.on('death', function (worker) {
//
delete workers[worker.pid];
worker = cluster.fork();
workers[worker.pid] = worker;
});
// CPU
for (var i = 0; i < numCPUs; i++) {
var worker = cluster.fork();
workers[worker.pid] = worker;
}
} else {
//
var app = require('./app');
app.listen(3000);
}
//
process.on('SIGTERM', function () {
for (var pid in workers) {
process.kill(pid);
}
process.exit(0);
});

cluster.js CPU CPU

cluster

10

142

Node.js

node cluster.js node 8


CPU
12408
12411
12412
12414
12416
12418
12420
12422
12424

?
?
?
?
?
?
?
?
?

00:01:28
00:01:27
00:01:28
00:01:31
00:01:34
00:01:44
00:01:38
00:01:34
00:02:14

node
node
node
node
node
node
node
node
node

6.3.3
Linux
/etc/init.d/ /etc/init.d/nginx start /etc/init.d/
nginx stop Nginx bash

microblog chmod +x microblog


#! /bin/sh
NODE_ENV=production
DAEMON="node cluster.js"
NAME=Microblog
DESC=Microblog
PIDFILE="microblog.pid"
case "$1" in
start)
echo "Starting $DESC: "
nohup $DAEMON > /dev/null &
echo $! > $PIDFILE
echo "$NAME."
;;
stop)
echo "Stopping $DESC: "
pid='cat $PIDFILE'
kill $pid
rm $PIDFILE
echo "$NAME."
;;
esac
exit 0

6.3

Node.js

143

nohup
pid microblog.pid microblog.pid pid

./microblog start
Starting Microblog:
Microblog.

microblog.pid
./microblog stop

DAEMON PIDFILE

4
POSIX LinuxMac OS Windows

6.3.4 80

3000:3000
HTTP 8080
app.js 80

PHP

IP
HTTPNginxApacheIISNginx

Node.js
Nginx
server {
listen 80;
server_name mysite.com;
location / {
proxy_pass http://localhost:3000;
}

mysite.com 80
http://localhost:3000Node.js http://mysite.com/

10

144

Node.js

http://localhost:3000
Nginx
Nginxapp.js app.use(express.static(__dirname + '/public'));
Nginx Node.js

6.4

Node.js
Node.js

Silver Bullet

Fred Brooks1987 No Silver Bullet

The Mythical Man-Month

Node.js

Node.js
Node.js
Node.js

Node.js
Node.js

IBM OS/360

6.4

Node.js

145

Node.js
Node.js

1.
Node.js 0.8 Node.js
Node.js

Node.js

Node.jsCPU

CPU 200200

Web

2.

Node.js

Node.js

3.
Node.js

I/O

Node.js

10

146

Node.js

4. Unicode
Node.js Unicodestring Node.js
JavaScript JavaScript UCS2
Unicode 65536

2000 Unicode
65536Unicode
WindowsJava JavaScript
Unicode 2UCS44
Unicode UCS2 UTF-16
UCS2UTF-16 UCS2

UCS2
UTF-16 UCS2
UTF-8 UTF-32 UCS4 4

JavaScript UCS2 UTF-16


UCS4 JavaScript V8
Node.js Node.js
string Buffer

6.5

Node.js
Node.js : http://www.infoq.com/cn/articles/

nodejs-module-mechanism
Node WebDavid Herron
: http://club.cnodejs.org/topic/4f6f057f8a04d82a3d0d230a
What Is Node? JavaScript Breaks Out of the Browser: http://shop.oreilly.com/product/06369

20021506. do
Node.js : http://www.ibm.com/developerworks/

cn/opensource/os-nodejs/
Node.js is Cancer: http://teddziuba.com/2011/10/node-js-is-cancer.html
Node.js is Candy: http://xentac.net/2011/10/05/1-nodejs-is-candy.html
V8 does not support UCS 4 characters: http://code.google.com/p/v8/issues/ detail?id=1697

A JavaScript

147

JavaScript

10

148

JavaScript

JavaScript JavaScript
VBScript
JavaScript
JavaScript

JavaScript JavaScript Brendan


Eich Gmail
Web 2.0 JavaScript
JavaScript ECMAScript
JavaScript
Node.js
JavaScript
lambda
JavaScript
functional programming
JavaScript JavaScript
JavaScript

A.1

scope

CC++Java JavaScript
block scope
C JavaScript
if (true) {
var somevar = 'value';
}
console.log(somevar); // value

JavaScript iffor

A.1.1
C JavaScript

A JavaScript

149

JavaScript

var v1 = 'v1';
var f1 = function() {
console.log(v1); // v1
};
f1();
var f2 = function() {
var v1 = 'local';
console.log(v1); // local
};
f2();

JavaScript

var scope = 'global';


var f = function() {
console.log(scope); // undefined
var scope = 'f';
}
f();

globalundefined
JavaScript console.log scope

JavaScript f f scope
scope console.log scope
undefined

undefined
var
undefined JavaScript

undefined

10

150

JavaScript

var f = function() {
var scope = 'f0';
(function() {
var scope = 'f1';
(function() {
console.log(scope); // f1
})();
})();
};
f();

scope
scope

JavaScript

var scope = 'top';


var f1 = function() {
console.log(scope);
};
f1(); // top
var f2 = function() {
var scope = 'f2';
f1();
};
f2(); // top

f2 f1 scope
scope f2 scope

A.1.2
JavaScript Node.js global
window

A JavaScript

151

var

A.2

closure 20 60

Scheme LISP

A.2.1
JavaScript

var generateClosure = function() {


var count = 0;
var get = function() {
count ++;
return count;
};
return get;
};

7
var counter = generateClosure();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

generateClosure() count 0

get get generateClosure() count


1 count generateClosure() get
counter generateClosure() get
counter() 1

count
generateClosure generateClosure

generateClosure count

10

152

JavaScript

generateClosure() counter() count


counter() count

generateClosure() get counter counter


generateClosure()

var generateClosure = function() {


var count = 0;
var get = function() {
count ++;
return count;
};
return get;
};
var counter1 = generateClosure();
var counter2 = generateClosure();
console.log(counter1()); // 1
console.log(counter2()); // 1
console.log(counter1()); // 2
console.log(counter1()); // 3
console.log(counter2()); // 2

counter1 counter2 generateClosure() count

generateClosure() get get


generateClosure() count
generateClosure() counter1
counter2

A.2.2
1.

Node.js MongoDB

A JavaScript

153

exports.add_user = function(user_info, callback) {


var uid = parseInt(user_info['uid']);
mongodb.open(function(err, db) {
if (err) {callback(err); return;}
db.collection('users', function(err, collection) {
if (err) {callback(err); return;}
collection.ensureIndex("uid", function(err) {
if (err) {callback(err); return;}
collection.ensureIndex("username", function(err) {
if (err) {callback(err); return;}
collection.findOne({uid: uid}, function(err) {
if (err) {callback(err); return;}
if (doc) {
callback('occupied');
} else {
var user = {
uid: uid,
user: user_info,
};
collection.insert(user, function(err) {
callback(err);
});
}
});
});
});
});
});
};

Node.js MongoDB

callback uid

2.
JavaScript

JavaScript_myPrivateProp

10

154

JavaScript

var generateClosure = function() {


var count = 0;
var get = function() {
count ++;
return count;
};
return get;
};
var counter = generateClosure();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

counter() count
1 count

JavaScripthttp://javascript.crockford.com/private.html

A.3

C++Java

PythonRuby JavaScript

JavaScript JavaScript JavaScript

JavaScript
JavaScript JavaScript
JavaScript

A.3.1
JavaScript
JavaScript

A JavaScript

155

JavaScript
var foo = {};
foo.prop_1 = 'bar';
foo.prop_2 = false;
foo.prop_3 = function() {
return 'hello world';
}
console.log(foo.prop_3());

var foo = {}; foo


foo.prop1 {} var

foo = new Object()

1.

var foo = {};


foo['prop1'] = 'bar';
foo['prop2'] = false;
foo['prop3'] = function() {
return 'hello world';
}

JavaScript
this

var some_prop = 'prop2';


foo[some_prop] = false;

2.
JavaScript

var foo = {
'prop1': 'bar',
prop2: 'false',
prop3: function (){
return 'hello world';
}
};

10

156

JavaScript

A.3.2

C++
JavaScript

function User(name, uri) {


this.name = name;
this.uri = uri;
this.display = function() {
console.log(this.name);
}
}

new
var someuser = new User('byvoid', 'http://www.byvoid.com');

someuser

A.3.3
JavaScript this
JavaScript
this
JavaScript C++ this

this

var someuser = {
name: 'byvoid',
display: function() {
console.log(this.name);
}
};
someuser.display(); // byvoid
var foo = {

A JavaScript

157

bar: someuser.display,
name: 'foobar'

};
foo.bar(); // foobar

JavaScript

foo bar someuser.display foo.bar()


bar foo this

JavaScript

var someuser = {
name: 'byvoid',
func: function() {
console.log(this.name);
}
};

var foo = {
name: 'foobar'
};
someuser.func(); // byvoid

foo.func = someuser.func;
foo.func(); // foobar
name = 'global';
func = someuser.func;
func(); // global

this
JavaScript

1. call apply
JavaScript call apply

JavaScript call apply

JavaScript

10

158

JavaScript

call
apply call
call apply call

apply call apply


func.call(thisArg[, arg1[, arg2[, ...]]])
func.apply(thisArg[, argsArray])

func thisArg func arg1arg2


argsArray func call
var someuser = {
name: 'byvoid',
display: function(words) {
console.log(this.name + ' says ' + words);
}
};
var foo = {
name: 'foobar'
};
someuser.display.call(foo, 'hello'); // foobar says hello

Node.js foobarsomeuser.display
call foo this.name
foo.namefoobar
2. bind
call apply

bind
bind
func.bind(thisArg[, arg1[, arg2[, ...]]])

func thisArg arg1arg2


bind thisArg func bind

var someuser = {
name: 'byvoid',
func: function() {
console.log(this.name);

A JavaScript

159

}
};
var foo = {
name: 'foobar'
};

foo.func = someuser.func;
foo.func(); // foobar
foo.func1 = someuser.func.bind(someuser);
foo.func1(); // byvoid

func = someuser.func.bind(foo);
func(); // foobar
func2 = func;
func2(); // foobar

foo.func someuser.func foo.func() this


foo foobarfoo.func1 bind someuser
this someuser.func foo.func1() this someuser

byvoid func bind foo this


someuser.func func() this foo foobar
func2 func func
3. bind
bind
var person = {
name: 'byvoid',
says: function(act, obj) {
console.log(this.name + ' ' + act + ' ' + obj);
}
};

person.says('loves', 'diovyb'); // byvoid loves diovyb


byvoidLoves = person.says.bind(person, 'loves');
byvoidLoves('you'); // byvoid loves you

byvoidLoves this person

loves byvoidLoves

10

160

JavaScript

4. bind
bind
var someuser = {
name: 'byvoid',
func: function () {
console.log(this.name);
}
};
var foo = {
name: 'foobar'
};
func = someuser.func.bind(foo);
func(); // foobar
func2 = func.bind(someuser);
func2(); // foobar

func someuser.func.bindthisfoofunc()
foobar func2 func bind this
someuserfunc2foobar this foo

bind
bind

someuser.func.bind = function(self) {
return this.call(self);
};

someuser.func bind this


someuser.func this.call(self) self
this someuser.func
//func = someuser.func.bind(foo)
func = function() {
return someuser.func.call(foo);
};
//func2 = func.bind(someuser)
func2 = function() {
return func.call(someuser);
};

func2 someuser func this


func func this bind

A JavaScript

161

A.3.4

JavaScript
Java C++
JavaScript

100%
new

function Person() {
}
Person.prototype.name = 'BYVoid';
Person.prototype.showName = function () {
console.log(this.name);
};
var person = new Person();
person.showName();

function Foo() {
var innerVar = 'hello';
this.prop1 = 'BYVoid';
this.func1 = function(){
innerVar = '';
};
}
Foo.prototype.prop2 = 'Carbo';
Foo.prototype.func2 = function () {
console.log(this.prop2);

10

162

JavaScript

};
var foo1 = new Foo();
var foo2 = new Foo();
console.log(foo1.func1 == foo2.func1); // false
console.log(foo1.func2 == foo2.func2); // true

JavaScript

JavaScript Object Function


Object.prototype Function.prototype
JavaScript
new
new
prototype __proto__
Object.prototype
prototype
__proto__ prototype constructor

function Foo() {
}
Object.prototype.name = 'My Object';
Foo.prototype.name = 'Bar';
var obj = new Object();
var foo = new Foo();
console.log(obj.name); // My Object
console.log(foo.name); // Bar
console.log(foo.__proto__.name); // Bar
console.log(foo.__proto__.__proto__.name); // My Object
console.log(foo. __proto__.constructor.prototype.name); // Bar

Foo () foo Object


Foo

A JavaScript

163

A-1

6
A-1

JavaScript

JavaScript prototype chain

foo foo. __proto__ foo. __proto__.__proto__

foo.constructorfoo.
__proto__Foo.prototype
foo.toStringfoo. __proto__.__proto__

Object.prototype

A.3.5
JavaScript Java C

Java clone
JavaScript

10

164

JavaScript

Object.prototype.clone = function() {
var newObj = {};
for (var i in this) {
newObj[i] = this[i];
}
return newObj;
}
var obj = {
name: 'byvoid',
likes: ['node']
};
var newObj = obj.clone();
obj.likes.push('python');
console.log(obj.likes); // [ 'node', 'python' ]
console.log(newObj.likes); // [ 'node', 'python' ]

shallow copy
likes

deep copy

Object.prototype.clone = function() {
var newObj = {};
for (var i in this) {
if (typeof(this[i]) == 'object' || typeof(this[i]) == 'function') {
newObj[i] = this[i].clone();
} else {
newObj[i] = this[i];
}
}
return newObj;
};
Array.prototype.clone = function() {
var newArray = [];
for (var i = 0; i < this.length; i++) {
if (typeof(this[i]) == 'object' || typeof(this[i]) == 'function') {
newArray[i] = this[i].clone();
} else {
newArray[i] = this[i];
}
}
return newArray;

A JavaScript

165

};
Function.prototype.clone = function() {
var that = this;
var newFunc = function() {
return that.apply(this, arguments);
};
for (var i in this) {
newFunc[i] = this[i];
}
return newFunc;
};
var obj = {
name: 'byvoid',
likes: ['node'],
display: function() {
console.log(this.name);
},
};
var newObj = obj.clone();
newObj.likes.push('python');
console.log(obj.likes); // [ 'node' ]
console.log(newObj.likes); // [ 'node', 'python' ]
console.log(newObj.display == obj.display); // false

var obj1 = {
ref: null
};
var obj2 = {
ref: obj1
};

obj1.ref = obj2;

obj1 obj2

10

Node.js

167

Node.js

10

168

Node.js

Node.jsNode.js
Node.js
Node.js
Node.jsJavaScript

Felixs Node.js Style Guidehttp://nodeguide.com/


style.htmlJavaScript

B.1

TabDelphiMicrosoft C++

PythonRubyC#
Node.js
Node.js

function func(boolVar) {
if (boolVar) {
console.log('True');
} else {
console.log('False');
}
};

function func(boolVar)
{
if (boolVar)
{
console.log('True');
}
else
{
console.log('False');
}
};

B.2

Node.js

169

80

B.3

JavaScriptC ; Python

var a = 1;
var b = 'world';
var c = function(x) {
console.log('hello ' + x + a);
};
c(b);

var a = 1
var b = 'world'
var c = function(x) {
console.log('hello ' + x + a)
}
c(b)

B.4

var
var

var ,

var
var
var
var

foo;
bar;
arr = [40, 'foo'];
obj = {};

10

170

Node.js

var foo, bar;


var arr = [40, 'foo'],
obj = {};

B.5

lower camel case

var yourName = 'BYVoid';

var YourName = 'BYVoid';


//
var your_name = 'BYVoid';

B.6

JavaScript

upper camel casePascal


{ }

var someFunction = function() {


return 'something';
};
function anotherFunction() {
return 'anything';
}
function DataStructure() {
this.someProperty = 'initialized';
}

Node.js

171

var SomeFunction = function()


{
return 'something';
};
function another_function () {
return 'anything';
}

function dataStructure() {
this.someProperty = 'initialized';}

B.7

JavaScript ' "


JSONXML 4

console.log('Hello world.');

console.log("Hello world.");

B.8

var = { };

var anObject = {
name: 'BYVoid',
website: 'http://www.byvoid.com/',
'is good': true,
};

var anObject = {'name': 'BYVoid',


website: 'http://www.byvoid.com/'
, "is good": true};

B.9

=== == ==

10

172

Node.js

num == literaltrue

var num = 9;
var literal = '9';
if (num === literal) {
console.log('Should not be here!!!');
}

var num = 9;
var literal = '9';
if (num == literal) {
console.log('Should not be here!!!');
}

B.10

Node.jsAPI
err undefined

req.on('end', function onEnd(err, message) {


if (err) {
console.log('Error.');
}
});
function FooObj() {
this.foo = 'bar';
}

req.on('end', function (message, err) {


if (err === false) {
console.log('Error.');
}
});
var FooObj = function() {
this.foo = 'bar';
}

B.11

Node.js

173

new

function FooObj(bar) {
//
this.bar = bar;
this.arr = [1, 2, 3];
}
//
FooObj.prototype.func = function() {
console.log(this.arr);
};
var obj1 = new FooObj('obj1');
var obj2 = new FooObj('obj2');
obj1.arr.push(4);
obj1.func(); // [1, 2, 3, 4]
obj2.func(); // [1, 2, 3]

function FooObj(bar) {
this.bar = bar;
this.func = function() {
console.log(this.arr);
};
}
FooObj.prototype.arr = [1, 2, 3];
var obj1 = new FooObj('obj1');
var obj2 = new FooObj('obj2');
obj1.arr.push(4);
obj1.func(); // [1, 2, 3, 4]
obj2.func(); // [1, 2, 3, 4]

B.12

10

174

Node.js

Node.jsutilinheritsFooEventEmitter

var util = require('util');


var events = require('events');
function Foo() {
}
util.inherits(Foo, events.EventEmitter);

175

A
access log83
ACID108
ActionScript9
applet7
Asynchronous I/O I/O4~529~31
Atomicity
108

B
Binary JSONBSON108
block

2931
Blocking I/O I/O29

2
CouchDB11
C7

D
Deep Clone164
Django2
Document108
DOM
3
DRYDont Repeat Yourself121
Durability
108

BOM
3

ECMA
8~9

ECMAScript8~9

Call Back Function


3134
Carakan9
Chakra9
child_process140
Client JavaScript3
cluster140
CommonJS10
CommonJS PackagesCommonJS
38
Comprehensive Perl Archive NetworkCPAN41
Consistency108
console
60~61
console.error()61
console.log()60
console.trace()61
Context Object156

ECMA-2628

ejsEmbedded JavaScript98~99
error log138~140
Event2931
Event Loop
29
EventEmitter.emit()64

EventEmitter.on()64
EventEmitter.once()64
EventEmitter.removeAllListeners()65
EventEmitter.removeListener()64
events.EventEmitter64~65

exports35
Express83~86
XSLTExtensible Stylesheet Language Transformations

97

Cookie110~111
Core JavaScript3

Field108

Core Modules
132

File Descriptor67

10

176

File Modules
132
Foreign Key
108

fs.open67

Lexical Scope150

fs.read68

Libeio6

fs.readFile66

Libev6

fs.readFileSync67

Libuv6

FTP110

LiveScript7
LiveWire7
Load Caching
134
Local Mode
42

Global Link
43
Global Mode
42
Global Object
58150
Global Scope150

H
http.ClientRequest76
http.ClientResponse77
http.createServer71

M
Microsoft SQL Server108
Middleware97
Module
35
module.exports36~38
MongoDB108
MVC
80
MySQL108

http.get76
http.request76
http.Server70

http.ServerRequest71
http.ServerResponse74

I
Index
108
IOCPInput/Output Completion Port6

Nitro9
node_modules133
Node
Node Package Managernpm41
Nombas41
Non-blocking I/O
I/O
29
NoSQLNot Only SQL107

ISO
8
ISO-162628
Isolation
108

J
JaegerMonkey9

O
Once And Only Once121
Opera9
Oracle108
ORMObject Relation Model83

Java applet7
JITJust-in-time Compilation
3

K
KJS9
Konqueror9

P
Package38~39
PHPPersonal Home Page Tools
97
pearPHP Extension and Application Repository43
Pingback70


PostgreSQL108
Primary Key
108
process58~59
process.argv59
process.execPath60
process.memoryUsage()60
process.nextTick()59
process.pid60
process.platform60
process.stdin59
process.stdout59
Prototype161
Prototype Chain
162
Python Package Indexpip
42

177

Safari9
ScriptEase7
Semantic Versioning
39
Sequence of Loading

134

Session

110
Shallow Clone
164
Smalltalk80
SpiderMonkey9
SQLStructured Query Language108

SQLite108
Squirrelfish10
Static Scope
150

Q
QtScript9

R
Rails83
Real-time Web Web2
REPLRead-eval-print loop25
Request Body
72
Request Header
72
request.abort76
request.pause77
request.resume77
request.setEncoding77
request.setNoDelay76
request.setSocketKeepAlive76
request.setTimeout76
require35
response.end74
response.write74
response.writeHead74
RESTRepresentational State Transfer

stderr60
stdout
60
Synchronous I/O I/O4~529~31

T
Table108

Rhino11

Template Engine97
TraceMonkey10
Transaction
107

Twitter Bootstrap104

U
Unique Key108
url.parse73
util.debug()63
util.format()63
util.inherits()61
util.inspect()62
util.isArray()63
util.isDate()63
util.isError()63
util.isRegExp()63

RingoJS11

V83

Row
108

View Helper
100

gemRuby gems42

Telnet110

94
Revers Proxy
143

Virtual Host
143

10

178

Foreign Key108

W3CWorld Wide Web Consortium


9

WebReal-time Web2

Field108

WebKit10

Object Relation Model ORM83

WMLScript9

I/OAsynchronous I/O4~529~31
Unique Key108

X
XSLTExtensible Stylesheet Language Transformations

97

Symbols

Once And Only Once121

Consistency108
World Wide Web ConsortiumW3C9
Context Object156

Middleware97
Primary Key108
Event2931

Event Loop29
Transaction
107
Session
110
Global Scope150

Global Object58150

Global Mode42

Global Link43
108
148

Load Caching134
134
Sequence of Loading

Package38~39
Prototype161

Prototype Chain162

Atomicity108

Durability108

console60~61
File Descriptor67

File Modules132
Document108

DOM3

error log138~140

Local Mode42
stdout
60
stderr60

Core Modules132
Module
35

MVC80

Template Engine97

Shallow Clone164

BOM3
Deep Clone164

141
Index
108

Virtual Host143

Row
108

Table108

Representational State Transfer REST


94

View Helper100

access log83
Lexical Scope150

Request Body72

Request Header72
Read-eval-print loopREPL25

Reverse Proxy143

block
2931

XSLTExtensible Stylesheet

I/OBlocking I/O29

Language Transformations97

Isolation108

I/OSynchronous I/O4~529~31

Static Scope150

Call Back Function


3134

I/ONon-blocking I/O
29

You might also like