15. REPL
$ node
> for (var i = 0; i < 3; i++) {
... console.log(i);
... }
0
1
2
undefined
>
Monday, March 11, 13
16. REPL
.break Bricht ein Multiline Statement ab
.clear Zurücksetzen + .break (CTRL + C)
.exit Beendet die aktuelle Shell (CTRL + D)
.help Liste der Befehle
.save Speichert die aktuelle Session
.load Lädt eine gespeicherte Session
Monday, March 11, 13
28. V8 - GARBAGE COLLECTION
• Programmausführung wird angehalten
• Es wird nur ein Teil des Object Heaps geprüft
• V8 kennt alle Objekte und Pointer im Speicher
Monday, March 11, 13
29. KERNKOMPONENTEN
Standard Library
Node Bindings
V8 libuv
Eventloop async I/O
libev + libeio IOCP
Monday, March 11, 13
33. X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
X X X
Monday, March 11, 13
34. APPLIKATIONEN IN NODE.JS
var Star = function () {
this.name = 'X',
this.height = 20,
this.step = 2;
};
Star.prototype.top = function() {
...
};
Star.prototype.print = function () {
console.log(this.top().join('n'));
console.log(this.middle());
console.log(this.bottom().join('n'));
}
...
var star = new Star();
star.print();
Monday, March 11, 13
42. EIGENE MODULE
• OH: “Wenn ich mir das Zeug, das in Node programmiert
wurde, so ansehe, sieht das aus wie PHP3. Einfach von oben
nach unten, alles in einer Datei”
• Liegen in einer separaten Datei
• Exportieren Klassen, Objekte oder Funktionen
• Können an anderer Stelle eingebunden werden
Monday, March 11, 13
43. EIGENE MODULE
validator.js
exports.email = function (email) {
var regex = /^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/,
result = regex.exec(email);
if (result) {
return true;
}
return false;
};
Monday, March 11, 13
44. EIGENE MODULE
validator.js
exports.email = function (email) {
var regex = /^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/,
result = regex.exec(email);
if (result) {
return true;
}
return false;
};
Monday, March 11, 13
45. VERWENDUNG EIGENER
MODULE
modules.js
var validator = require('./validator.js'),
mail = ['sebastian.springer@mayflower.de', 'Invalid Address'];
for (var i = 0; i < mail.length; i++) {
if (validator.email(mail[i])) {
console.log((i + 1) + '. Mailadresse ist gültig');
} else {
console.log((i + 1) + '. Mailadresse ist ungültig');
}
}
Monday, March 11, 13
46. VERWENDUNG EIGENER
MODULE
modules.js
var validator = require('./validator.js'),
mail = ['sebastian.springer@mayflower.de', 'Invalid Address'];
for (var i = 0; i < mail.length; i++) {
if (validator.email(mail[i])) {
console.log((i + 1) + '. Mailadresse ist gültig');
} else {
console.log((i + 1) + '. Mailadresse ist ungültig');
}
}
Monday, March 11, 13
47. EIGENE MODULE
$ node modules.js
1. Mailadresse ist gültig
2. Mailadresse ist ungültig
Monday, March 11, 13
49. NPM
• Node Package Manager (von Isaac Schlueter)
• Bestandteil von Node.js seit 0.6.3
• https://github.com/isaacs/npm
Monday, March 11, 13
50. NPM - REPO
• Hier kommen die Pakete für das npm-Kommando her
• https://npmjs.org/
• Aktuell über 24.000 Pakete
• https://registry.npmjs.org/-/all/
Monday, March 11, 13
52. NPM SEARCH
$ npm se mysql
npm http GET https://registry.npmjs.org/-/all/since?stale=update_aft...
npm http 200 https://registry.npmjs.org/-/all/since?stale=update_aft...
NAME DESCRIPTION AUTHOR DATE KEYWORDS...
Accessor_M... A MySQL database wrapper... =bu 2012-1... mysql ac...
any-db Database-agnostic connec... =grncdr 2013-0... mysql po...
autodafe mvc framework for node w... =jifeon 2012-1... mvc fram...
backbone-m... A sync module for Backbo... =ccowan 2012-1...
caminte ORM for every database: ... =biggor 2013-0... caminte ...
connect-my... a MySQL session store fo... =nathan 2012-0...
connect-my... A MySQL session store fo... =daniel 2011-0...
cormo ORM framework for Node.j... =croqui 2013-0... orm mong...
Monday, March 11, 13
53. NPM INSTALL
$ npm in mysql
npm http GET https://registry.npmjs.org/mysql
npm http 200 https://registry.npmjs.org/mysql
npm http GET https://registry.npmjs.org/bignumber.js/1.0.1
npm http GET https://registry.npmjs.org/require-all/0.0.3
npm http 200 https://registry.npmjs.org/require-all/0.0.3
npm http GET https://registry.npmjs.org/require-all/-/requi...
npm http 200 https://registry.npmjs.org/bignumber.js/1.0.1
npm http GET https://registry.npmjs.org/bignumber.js/-/bign...
npm http 200 https://registry.npmjs.org/require-all/-/requi...
npm http 200 https://registry.npmjs.org/bignumber.js/-/bign...
mysql@2.0.0-alpha7 node_modules/mysql
!"" require-all@0.0.3
#"" bignumber.js@1.0.1
Monday, March 11, 13
54. NPM LIST
$ npm ls
/srv/node
#"$ mysql@2.0.0-alpha7
!"" bignumber.js@1.0.1
#"" require-all@0.0.3
Monday, March 11, 13
55. NPM UPDATE
$ npm up
npm http GET https://registry.npmjs.org/mysql
npm http 304 https://registry.npmjs.org/mysql
npm http GET https://registry.npmjs.org/require-all/0.0.3
npm http GET https://registry.npmjs.org/bignumber.js/1.0.1
npm http 304 https://registry.npmjs.org/bignumber.js/1.0.1
npm http 304 https://registry.npmjs.org/require-all/0.0.3
Monday, March 11, 13
56. NPM REMOVE
$ npm rm mysql
$ npm ls
/srv/node
#"" (empty)
Monday, March 11, 13
64. EVENTEMITTER
messageBus.js
var EventEmitter = require('events').EventEmitter,
util = require('util');
var MessageBus = function () {};
util.inherits(MessageBus, EventEmitter);
exports.MessageBus = MessageBus;
Monday, March 11, 13
65. EVENTEMITTER
events.js
var MessageBus = require('./messageBus.js').MessageBus;
var mb = new MessageBus();
mb.on('message', function (data) {
console.log('Received new message: ' + data)
});
mb.emit('message', 'Hello World');
Monday, March 11, 13
66. EVENTEMITTER
$ node events.js
Received new message: Hello World
Monday, March 11, 13
67. EVENTS
• Wo kommen Events zum Einsatz?
• child_process, cluster, dgram, domain, fs, http, net, readline,
repl, stream, tls
Monday, March 11, 13
93. APPEND FILE
$ cat input.txt
Hello World!
var fs = require('fs'),
data = process.argv[2] || 'Hello my World';
fs.appendFile('input.txt', data, function (err) {
if (err) {
console.error('Could not write into file');
return false;
}
console.log('Success!');
return true;
});
Monday, March 11, 13
94. APPEND FILE
$ cat input.txt
Hello World!
var fs = require('fs'),
data = process.argv[2] || 'Hello my World';
fs.appendFile('input.txt', data, function (err) {
if (err) {
console.error('Could not write into file');
return false;
}
console.log('Success!');
return true;
});
$ node appendFile.js 'Hallo München!'
Success!
$ cat input.txt
Hello World!Hallo München!
Monday, March 11, 13
95. WATCH FILE
var fs = require('fs');
fs.watch('input.txt', function (e) {
if (e === 'change') {
console.log('File changed');
} else if (e === 'rename') {
console.log('File renamed');
}
});
Monday, March 11, 13
96. WATCH FILE
var fs = require('fs');
fs.watch('input.txt', function (e) {
if (e === 'change') {
console.log('File changed');
} else if (e === 'rename') {
console.log('File renamed');
}
});
$ node watchFile.js
Monday, March 11, 13
97. WATCH FILE
var fs = require('fs');
fs.watch('input.txt', function (e) {
if (e === 'change') {
console.log('File changed');
} else if (e === 'rename') {
console.log('File renamed');
}
});
$ node watchFile.js
$ echo 'Hello World!' > input.txt
Monday, March 11, 13
98. WATCH FILE
var fs = require('fs');
fs.watch('input.txt', function (e) {
if (e === 'change') {
console.log('File changed');
} else if (e === 'rename') {
console.log('File renamed');
}
});
$ node watchFile.js
$ echo 'Hello World!' > input.txt
$ node watchFile.js
File changed
Monday, March 11, 13
110. CHILD_PROCESS
• spawn - Kommandoausführung
• exec - Kommandoausführung in Puffer
• execFile - Dateiausführung in Puffer
• fork - Node Prozess
Monday, March 11, 13
111. ETWAS RECHENINTENSIVES
cp1.js
module.exports = function () {
var i, n = 1, results = 1;
primeLoop: while (results < 300000) {
n += 1;
for (i = 2; i <= Math.sqrt(n); i += 1) {
if (n % i === 0) {
continue primeLoop;
}
}
results += 1;
}
return n;
};
Monday, March 11, 13
112. potenziell
ETWAS BLOCKIERENDES
cp2.js
var http = require('http');
http.createFakeServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello Worldn');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Monday, March 11, 13
113. ETWAS BLOCKIERENDES
cp3.js
var http = require('http'),
prime = require('./cp1.js');
http.createServer(function (req, res) {
console.time('Request answered in');
console.log('incoming Request');
var number = prime();
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello Worldn');
console.timeEnd('Request answered in');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Monday, March 11, 13
114. ETWAS BLOCKIERENDES
$ node cp3.js
Server running at http://127.0.0.1:1337/
incoming Request
Request answered in: 4713ms
incoming Request
Request answered in: 4703ms
Monday, March 11, 13
116. CHILD_PROCESS
cp4.js
var http = require('http');
http.createServer(function (req, res) {
console.time('Request answered in');
console.log('incoming Request');
require('child_process').fork('./primeHelper.js')
.on('message', function (data) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('The 300000st prime number is: ' + data.prime);
console.timeEnd('Request answered in');
});
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Monday, March 11, 13
117. CHILD_PROCESS
primeHelper.js
var prime = require('./cp1.js')();
process.send({'prime': prime});
Monday, March 11, 13
118. CHILD_PROCESS
$ node cp4.js
Server running at http://127.0.0.1:1337/
incoming Request
incoming Request
Request answered in: 4242ms
Request answered in: 4913ms
Monday, March 11, 13
119. CHILD_PROCESS
• Threadmodell von Node.js
• Möglichkeiten von child_process - fork, spawn, exec
• Kommunikation zwischen Eltern- und Kindprozess
Monday, March 11, 13
121. CLUSTER
• Loadbalancing über CPU
• Funktioniert mit allen Instanzen von “net.Server”
• ...auch mit http
Monday, March 11, 13
122. cluster.js
var cluster = require('cluster'),
http = require('http'),
workers = 2;
if (cluster.isMaster) {
for (var i = 0; i < workers; i++) {
cluster.fork();
}
} else {
console.log('Worker ' + cluster.worker.process.pid + ' started');
http.createServer(function(req, res) {
console.log('Worker ' + cluster.worker.process.pid + '
responds');
res.writeHead(200);
res.end("hello worldn");
}).listen(8000);
}
Monday, March 11, 13
123. clusterClient.js
var http = require('http');
for (var i = 0; i < 100; i++) {
http.get('http://localhost:8000', function (res) {
console.log(res);
});
}
Monday, March 11, 13
127. UNITTESTS
• Absicherung von Applikationen
• Tests auf Funktionsebene
• Node.js testet eigene Module ebenfalls
• Assert-Modul
• node-v0.8.22/test/simple
Monday, March 11, 13
129. ASSERTION TESTING
• var assert = require(‘assert’)
• Assertion-Methoden
• Sehr wenig Rückmeldung
• Nur ein Failure
Monday, March 11, 13
130. ASSERTION TESTING
fail Wirft einen
AssertionError
ok(value, [message]) Pass, wenn der Wert
true ist
equal(actual, expected, [message]) Vergleich mit ==
deepEqual(actual, expected, [message]) Vergleich über
Strukturen
strictEqual(actual, expected, [message]) Vergleich mit ===
throws(block, [error], [message]) Pass, wenn eine
Exception geworfen
wird
NOT! - notEqual(...)
Monday, March 11, 13
131. ASSERTION TESTING
assert.js
var assert = require('assert'),
actual = 'Hello World',
expected = 'Hello World';
assert.equal(actual, expected, 'Strings are not Equal');
assert.notEqual(actual, expected, 'Strings are Equal');
assert.fail('FAIL!', 'PASS!', 'This fails!');
Monday, March 11, 13
132. ASSERTION TESTING
$ node assert.js
assert.js:102
throw new assert.AssertionError({
^
AssertionError: Strings are Equal
at Object.<anonymous> (/tmp/node/assert.js:7:8)
at Module._compile (module.js:449:26)
at Object.Module._extensions..js (module.js:467:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.runMain (module.js:492:10)
at process.startup.processNextTick.process._tickCallback (node.js:
244:9)
Monday, March 11, 13
138. PROMISES
• Ergebnis eines asynchronen Funktionsaufrufs
• Rückgabewert oder Exception
• Promise statt Blocking
• CommonJS Proposal
• Bis 0.2 Bestandteil von Node
Monday, March 11, 13
139. PYRAMID OF DOOM
step1(function (value1) {
step2(value1, function (value2) {
step3(value2, function (value3) {
step3(value3, function (value4) {
// do something
});
});
});
});
Monday, March 11, 13
140. PROMISES
Q.fcall(step1)
.then(step2)
.then(step3)
.then(step4)
.then(function (value4) {
// do something with value 4
}, function (error) {
// Handle any error from step1 through step4
})
.end();
Monday, March 11, 13
148. KONTAKT
Sebastian Springer
sebastian.springer@mayflower.de
Mayflower GmbH
Mannhardtstr. 6
80538 München
Deutschland
@basti_springer
https://github.com/sspringer82
Monday, March 11, 13