einführung in node.js

Post on 22-Apr-2015

1.558 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

JavaScript Days 2013

TRANSCRIPT

Monday, March 11, 13

WER BIN ICH?

• Sebastian Springer

• https://github.com/sspringer82

• @basti_springer

• Teamlead @ Mayflower

Monday, March 11, 13

THEMEN• Installation

• Node.js Shell

• Kernkomponenten

• NPM

• Events

• Streams

• HTTP

• Dateisystem

• Debugger

• Child_Process

• Cluster

• Tests

• Promises

Monday, March 11, 13

INSTALLATION

Monday, March 11, 13

INSTALLATION

Monday, March 11, 13

INSTALLATIONAuf welchen Systemen ist Node.js verfügbar?

Monday, March 11, 13

INSTALLATION• Unix

• /usr/local/bin/node

• /usr/local/bin/npm

• /usr/local/lib/node_modules

• Windows

• C:\Program Files\nodejs\node.exe

• C:\Program Files\nodejs\npm

• C:\Program Files\nodejs\node_modules

Monday, March 11, 13

INSTALLATION

$ wget http://nodejs.org/dist/v0.8.21/node-v0.8.21.tar.gz...$ tar xvzf node-v0.8.21.tar.gz...$ cd node-v0.8.21/$ ./configure --prefix=/opt/node/node-v0.8.21...$ make...$ sudo make install...

Suchpfad anpassen!

Monday, March 11, 13

INSTALLATION

$ node --versionv0.8.22

Hat es funktioniert?

Monday, March 11, 13

REPL

Monday, March 11, 13

WHAT?

Monday, March 11, 13

READ-EVAL-PRINT-LOOP

DIE NODE.JS SHELL

Monday, March 11, 13

REPL

$ node> for (var i = 0; i < 3; i++) {... console.log(i);... }012undefined>

Monday, March 11, 13

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

KERNKOMPONENTEN

Monday, March 11, 13

KERNKOMPONENTENStandard Library

Node Bindings

V8 libuv

Eventloop async I/O

Monday, March 11, 13

KERNKOMPONENTENStandard Library

Node Bindings

V8 libuv

Eventloop async I/O

Monday, March 11, 13

KERNKOMPONENTEN

Monday, March 11, 13

KERNKOMPONENTENStandard Library

Node Bindings

V8 libuv

Eventloop async I/O

Monday, March 11, 13

KERNKOMPONENTENStandard Library

Node Bindings

V8 libuv

Eventloop async I/O

Monday, March 11, 13

V8

• Schneller Zugriff auf Eigenschaften

• Dynamische Erstellung von Maschinencode

• Garbage Collection

Monday, March 11, 13

V8 - FAST PROPERTY ACCESS

Monday, March 11, 13

V8 - FAST PROPERTY ACCESS

Monday, March 11, 13

V8 - FAST PROPERTY ACCESS

Monday, March 11, 13

MASCHINENCODE

Monday, March 11, 13

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

KERNKOMPONENTENStandard Library

Node Bindings

V8 libuv

Eventloop async I/O

libev + libeio IOCPMonday, March 11, 13

ASYNCHRONE OPERATIONEN

node.js Betriebssystem

Operation(z.B. lesen)

Monday, March 11, 13

APPLIKATIONEN IN NODE.JS

Monday, March 11, 13

APPLIKATIONEN IN NODE.JS

$ node helloWorld.js

Monday, March 11, 13

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 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 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 XX X X

Monday, March 11, 13

APPLIKATIONEN IN NODE.JSvar 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

DAS MODULSYSTEM

Monday, March 11, 13

DAS MODULSYSTEM

NPM

eigene Module

interne Module

Monday, March 11, 13

INTERNE MODULEAssertion Testing

BufferChild_Process

ClusterCrypto

DebuggerDNS

DomainEvent

File System

HTTPHTTPS

NetOsPath

ProcessQueryString

ReadlineREPL

Stream

String DecoderTimersTLS/SSL

TTYUDPURL

UtilitiesVMZLIB

Monday, March 11, 13

INTERNE MODULESTABILITÄTSINDEX

Index Name Beispiel

0 Deprecated util.pump

1 Experimental Domain, Cluster

2 Unstable Readline, Stream

3 Stable HTTP, Query String

4 API Frozen OS, Events

5 Locked Util, Assert

Monday, March 11, 13

VERWENDUNG INTERNER MODULE

var os = require('os');

console.log('Betriebssystem: ' + os.type() + ' ' + os.platform() + ' ' + os.release() + ' ' + os.arch());

intModule.js

Monday, March 11, 13

INTERNE MODULE - GLOBALS

• console

• process

• require

• Buffer

• set/clear-Timeout/Interval

• __filename + __dirname

Monday, March 11, 13

EIGENE MODULE

Monday, March 11, 13

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

EIGENE MODULE

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;};

validator.js

Monday, March 11, 13

EIGENE MODULE

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;};

validator.js

Monday, March 11, 13

VERWENDUNG EIGENER MODULE

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'); }}

modules.js

Monday, March 11, 13

VERWENDUNG EIGENER MODULE

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'); }}

modules.js

Monday, March 11, 13

EIGENE MODULE

$ node modules.js1. Mailadresse ist gültig2. Mailadresse ist ungültig

Monday, March 11, 13

Monday, March 11, 13

NPM

• Node Package Manager (von Isaac Schlueter)

• Bestandteil von Node.js seit 0.6.3

• https://github.com/isaacs/npm

Monday, March 11, 13

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

KOMMANDOS

• npm search <package>

• npm install <package>

• npm list

• npm update

• npm remove

Monday, March 11, 13

NPM SEARCH

$ npm se mysqlnpm 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

NPM INSTALL$ npm in mysqlnpm http GET https://registry.npmjs.org/mysqlnpm http 200 https://registry.npmjs.org/mysqlnpm http GET https://registry.npmjs.org/bignumber.js/1.0.1npm http GET https://registry.npmjs.org/require-all/0.0.3npm http 200 https://registry.npmjs.org/require-all/0.0.3npm http GET https://registry.npmjs.org/require-all/-/requi...npm http 200 https://registry.npmjs.org/bignumber.js/1.0.1npm 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

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

NPM UPDATE

$ npm upnpm http GET https://registry.npmjs.org/mysqlnpm http 304 https://registry.npmjs.org/mysqlnpm http GET https://registry.npmjs.org/require-all/0.0.3npm http GET https://registry.npmjs.org/bignumber.js/1.0.1npm http 304 https://registry.npmjs.org/bignumber.js/1.0.1npm http 304 https://registry.npmjs.org/require-all/0.0.3

Monday, March 11, 13

NPM REMOVE

$ npm rm mysql$ npm ls/srv/node#"" (empty)

Monday, March 11, 13

EIGENE NPM-PAKETE

Monday, March 11, 13

{ "author": { "name": "Felix Geisendörfer", "email": "felix@debuggable.com", "url": "http://debuggable.com/" }, "name": "mysql", "description": "A node.js driver for mysql...", "version": "2.0.0-alpha7", "repository": { "url": "" }, "main": "./index", "scripts": { "test": "make test" }, "engines": { "node": "*" }, "dependencies": { "require-all": "0.0.3", "bignumber.js": "1.0.1" }, "devDependencies": { "utest": "0.0.6", "urun": "0.0.6", "underscore": "1.3.1" }, "optionalDependencies": {}, "readme": "# node-mysql\n\n[![Build Status]...", "readmeFilename": "Readme.md", "_id": "mysql@2.0.0-alpha7", "_from": "mysql"}

Monday, March 11, 13

EIGENE NPM-PAKETE

• npm adduser

• Username, Passwort, E-Mail

• npm publish <folder>|<tarball>

Monday, March 11, 13

EVENTS

Monday, March 11, 13

EVENTSEvent Emitter Subscriber

on(‘message’, function (e) {...

emit(‘message’, ‘data’)

Monday, March 11, 13

EVENTS

• Basis vieler Module

• Grundlage für eventgetriebene Architektur

• Ereignisse zum Informationsaustausch

• emit(event, [arg1], [arg2], [...]) - Publish

• on(event, listener) - Subscribe

Monday, March 11, 13

EVENTEMITTER

var EventEmitter = require('events').EventEmitter, util = require('util');

var MessageBus = function () {};

util.inherits(MessageBus, EventEmitter);

exports.MessageBus = MessageBus;

messageBus.js

Monday, March 11, 13

EVENTEMITTER

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');

events.js

Monday, March 11, 13

EVENTEMITTER

$ node events.js Received new message: Hello World

Monday, March 11, 13

EVENTS

• Wo kommen Events zum Einsatz?

• child_process, cluster, dgram, domain, fs, http, net, readline, repl, stream, tls

Monday, March 11, 13

STREAMS

Monday, March 11, 13

STREAMS

• Repräsentieren Datenströme in Node.js

• Abstraktes Interface

• Les- und/oder schreibbare Streams

Monday, March 11, 13

READABLE STREAM

• Events

• data

• end

• error

• close

• Methoden

• pause

• resume

• destroy

• pipe

• setEncoding

Monday, March 11, 13

WRITABLE STREAM

• Events

• drain

• error

• close

• pipe

• Methoden

• write

• end

• destroy

• destroySoon

Monday, March 11, 13

STREAMS

• Wo kommen Streams zum Einsatz?

• fs, http, net repl, tls, zlib

Monday, March 11, 13

STREAMS IN DER PRAXIS?

Monday, March 11, 13

http://www.google.com

Monday, March 11, 13

DER KLASSIKER

Monday, March 11, 13

HTTP-SERVER

var http = require('http');

http.createServer(function (req, res) { res.end('Hello World');}).listen(8080);

http.js

Monday, March 11, 13

HTTP-SERVER$ node http.js

Monday, March 11, 13

require('http').createServer(function (req, res) { var body, status, reqData;

if (req.headers['user-agent'].search(/MSIE/) != -1) { body = 'wrong Browser'; status = 403; } else { body = 'Hello Client'; status = 200; }

req.on('data', function (data) { reqData += data; }).on('end', function () { if (reqData) console.log(reqData); });

res.writeHead(status, { 'Content-Length': body.length, 'Content-Type': 'text/plain' }); res.write(body); res.end();}).listen(8080);

Monday, March 11, 13

HTTP-SERVER

• http.ServerRequest: Readable Stream

• http.ServerResponse: Writable Stream

Monday, March 11, 13

HTTP-CLIENT?

Monday, March 11, 13

var options = { hostname: 'www.google.de', port: 80, path: '/', method: 'get'};

var req = require('http').request(options, function(res) { console.log(res); res.setEncoding('utf8'); res.on('data', function (chunk) { console.log('BODY: ' + chunk); });});

req.on('error', function(e) { console.log('problem with request: ' + e.message);});

req.write('data\n');req.end();

Monday, March 11, 13

var options = { hostname: 'www.google.de', port: 80, path: '/', method: 'get'};

var req = require('http').request(options, function(res) { console.log(res); res.setEncoding('utf8'); res.on('data', function (chunk) { console.log('BODY: ' + chunk); });});

req.write('data\n');req.end();

Monday, March 11, 13

DATEISYSTEM

Monday, March 11, 13

DATEISYSTEM-FUNKTIONEN

• exists

• readFile

• writeFile

• appendFile

• watchFile

• rename

• unlink

• chmod

• chown

• ...

Monday, March 11, 13

SYNC VS. ASYNC

Monday, March 11, 13

DATEI LESEN

var fs = require('fs') filename = process.argv[2] || 'input.txt';

fs.readFile(filename, 'utf8', function (err, data) { if (err) { console.error("File cound not be opened"); return false; } console.log(data); return true;});

Monday, March 11, 13

DATEI LESEN

$ node readFile.jsHello World!

Monday, March 11, 13

DATEI LESEN

$ node readFile.jsHello World!

$ node readFile.js nonexistant.txtFile cound not be opened

Monday, March 11, 13

FILE EXISTS$ ls -l input.txt -rw-r--r-- 1 sspringer staff 12 Mar 7 09:06 input.txt

Monday, March 11, 13

FILE EXISTS$ ls -l input.txt -rw-r--r-- 1 sspringer staff 12 Mar 7 09:06 input.txt

var fs = require('fs'), filename = process.argv[2] || 'input.txt';

fs.exists(filename, function (exists) { if (exists) { console.log('File exists'); return true; } console.error('There is no such file'); return false;});

Monday, March 11, 13

FILE EXISTS$ ls -l input.txt -rw-r--r-- 1 sspringer staff 12 Mar 7 09:06 input.txt

var fs = require('fs'), filename = process.argv[2] || 'input.txt';

fs.exists(filename, function (exists) { if (exists) { console.log('File exists'); return true; } console.error('There is no such file'); return false;});

$ node fileExists.jsFile exists

Monday, March 11, 13

APPEND FILE$ cat input.txtHello World!

Monday, March 11, 13

APPEND FILE$ cat input.txtHello 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

APPEND FILE$ cat input.txtHello 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

WATCH FILEvar 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

WATCH FILE

$ node watchFile.js

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

WATCH FILE

$ echo 'Hello World!' > input.txt

$ node watchFile.js

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

WATCH FILE

$ echo 'Hello World!' > input.txt

$ node watchFile.js

$ node watchFile.js File changed

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

DEBUGGER

Monday, March 11, 13

BEISPIELCODEvar myObj = {a: 1, b: 2};

console.log(myObj);

myObj.a = 'Hello';

console.log(myObj);

for (var i = 0; i < 10; i++) { var helper = function () { // do something console.log(i) }; helper();}

Monday, March 11, 13

DEBUGGER

$ node debug debugger.js< debugger listening on port 5858connecting... okbreak in debugger.js:1 1 var myObj = {a: 1, b: 2}; 2 3 console.log(myObj);debug>

Monday, March 11, 13

DEBUGGER

$ node debug debugger.js< debugger listening on port 5858connecting... okbreak in debugger.js:1 1 var myObj = {a: 1, b: 2}; 2 3 console.log(myObj);debug>

Monday, March 11, 13

DEBUGGER - STEP

Kommando Bedeutung Beschreibung

n next Fortsetzen

c cont Step over

s step Step in

o out Step out

Monday, March 11, 13

DEBUGGER - WATCH

• watch(expression)

• unwatch(expression)

• watchers

Monday, March 11, 13

DEBUGGER - WATCH

debug> watch('myObj')debug> nbreak in debugger.js:3Watchers: 0: myObj = {"b":2,"a":1}

1 var myObj = {a: 1, b: 2}; 2 3 console.log(myObj); 4 5 myObj.a = 'Hello';debug>

Monday, March 11, 13

DEBUGGER - WATCH

debug> watch('myObj')debug> nbreak in debugger.js:3Watchers: 0: myObj = {"b":2,"a":1}

1 var myObj = {a: 1, b: 2}; 2 3 console.log(myObj); 4 5 myObj.a = 'Hello';debug>

Monday, March 11, 13

DEBUGGER - REPLdebug> replPress Ctrl + C to leave debug repl> myObj{ b: 2, a: 1 }> myObj.b = 14;14> myObj{ b: 14, a: 1 }debug> n< { a: 1, b: 14 }break in debugger.js:5Watchers: 0: myObj = {"b":14,"a":1}

3 console.log(myObj); 4 5 myObj.a = 'Hello'; 6 7 console.log(myObj);debug>

Monday, March 11, 13

DEBUGGER

• Kommandozeilen Debugger

• Kommandos

• Debugging einer Applikation

Monday, March 11, 13

CHILD_PROCESS

Monday, March 11, 13

CHILD_PROCESS

• spawn - Kommandoausführung

• exec - Kommandoausführung in Puffer

• execFile - Dateiausführung in Puffer

• fork - Node Prozess

Monday, March 11, 13

ETWAS RECHENINTENSIVES

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;};

cp1.js

Monday, March 11, 13

ETWAS BLOCKIERENDESpotenziell

var http = require('http');

http.createFakeServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n');}).listen(1337, '127.0.0.1');

console.log('Server running at http://127.0.0.1:1337/');

cp2.js

Monday, March 11, 13

ETWAS BLOCKIERENDES

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 World\n');

console.timeEnd('Request answered in');}).listen(1337, '127.0.0.1');

console.log('Server running at http://127.0.0.1:1337/');

cp3.js

Monday, March 11, 13

ETWAS BLOCKIERENDES

$ node cp3.js Server running at http://127.0.0.1:1337/incoming RequestRequest answered in: 4713msincoming RequestRequest answered in: 4703ms

Monday, March 11, 13

DIE LÖSUNG: WIR FORKEN

Monday, March 11, 13

CHILD_PROCESS

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/');

cp4.js

Monday, March 11, 13

CHILD_PROCESS

primeHelper.js

var prime = require('./cp1.js')();

process.send({'prime': prime});

Monday, March 11, 13

CHILD_PROCESS

$ node cp4.js Server running at http://127.0.0.1:1337/incoming Requestincoming RequestRequest answered in: 4242msRequest answered in: 4913ms

Monday, March 11, 13

CHILD_PROCESS

• Threadmodell von Node.js

• Möglichkeiten von child_process - fork, spawn, exec

• Kommunikation zwischen Eltern- und Kindprozess

Monday, March 11, 13

CLUSTER

Monday, March 11, 13

CLUSTER

• Loadbalancing über CPU

• Funktioniert mit allen Instanzen von “net.Server”

• ...auch mit http

Monday, March 11, 13

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 world\n"); }).listen(8000);}

cluster.js

Monday, March 11, 13

var http = require('http');

for (var i = 0; i < 100; i++) { http.get('http://localhost:8000', function (res) { console.log(res); });}

clusterClient.js

Monday, March 11, 13

CLUSTER

• node cluster.js

• node clusterClient.js

Monday, March 11, 13

CLUSTERWorker 38128 respondsWorker 38128 respondsWorker 38127 respondsWorker 38127 respondsWorker 38128 respondsWorker 38127 respondsWorker 38128 respondsWorker 38127 respondsWorker 38127 respondsWorker 38127 respondsWorker 38128 respondsWorker 38127 respondsWorker 38128 respondsWorker 38127 respondsWorker 38128 respondsWorker 38127 respondsWorker 38127 respondsWorker 38128 respondsWorker 38127 responds

Monday, March 11, 13

TESTING

Monday, March 11, 13

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

ASSERTION TESTING

Monday, March 11, 13

ASSERTION TESTING

• var assert = require(‘assert’)

• Assertion-Methoden

• Sehr wenig Rückmeldung

• Nur ein Failure

Monday, March 11, 13

ASSERTION TESTINGfail Wirft einen

AssertionErrorok(value, [message]) Pass, wenn der Wert

true istequal(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

ASSERTION TESTING

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!');

assert.js

Monday, March 11, 13

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

NODEUNIT

Monday, March 11, 13

NODEUNIT

• npm install -g nodeunit

• Die gleichen Assertion-Methoden wie im Assert-Modul

• More verbose

• Mehrere Failures

Monday, March 11, 13

module.exports = { setUp: function (callback) { console.log('setUp'); callback(); }, tearDown: function (callback) { console.log('tearDown'); callback(); }, firstExample: function (test) { console.log('firstExample') test.equal('Hello', 'Hello', 'Strings are not Equal'); test.done(); }, exampleGroup: { secondExample: function (test) { test.notEqual('Hello', 'Hello', 'Strings are Equal'); test.done(); }, thirdExample: function (test) { test.fail('FAIL!', 'PASS!', 'This fails!'); test.done(); } }}

Monday, March 11, 13

$ nodeunit nodeunit.js

nodeunit.jssetUpfirstExampletearDown✔ firstExamplesetUptearDown✖ exampleGroup - secondExample

Assertion Message: Strings are EqualAssertionError: 'Hello World' != 'Hello World' at Object.assertWrapper [as notEqual] (...

setUptearDown✖ exampleGroup - thirdExample

AssertionError: 'FAIL!' undefined 'PASS!' at Object.assertWrapper [as fail] (...

FAILURES: 2/3 assertions failed (5ms)

Monday, March 11, 13

PROMISES

Monday, March 11, 13

PROMISES

• Ergebnis eines asynchronen Funktionsaufrufs

• Rückgabewert oder Exception

• Promise statt Blocking

• CommonJS Proposal

• Bis 0.2 Bestandteil von Node

Monday, March 11, 13

PYRAMID OF DOOM

step1(function (value1) { step2(value1, function (value2) { step3(value2, function (value3) { step3(value3, function (value4) { // do something }); }); });});

Monday, March 11, 13

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

PROMISE-LIBRARIES

• https://github.com/kriskowal/q

• https://github.com/kriszyp/node-promise (lightweight)

• https://github.com/kriszyp/promised-io (complete API)

• ...

Monday, March 11, 13

OHNE PROMISESvar fs = require('fs');

fs.exists('input.txt', function (exists) { fs.stat('input.txt', function (err, stats) { fs.open('input.txt', 'r+', function (err, fd) { fs.read(fd, new Buffer(stats.size), 0, stats.size, null, function (err, read, buff) { if (err) throw err; console.log(buff.toString()); fs.close(fd, function () { console.log('File Handle closed'); }); } ) }); });});

Monday, March 11, 13

MIT PROMISES

Monday, March 11, 13

var fs = require('promised-io/fs'), gStat, gFd;

var open = function (stat) { gStat = stat; return fs.open('input.txt', 'r+'); }, read = function (fd) { gFd = fd; return fs.read(fd, new Buffer(gStat.size), 0, gStat.size, null); }, close = function (args) { console.log(args[1].toString()); return fs.close(gFd); }, catchall = function (err) { console.log(err); }, finished = function () { console.log('File Handle closed'); };

fs.stat('input.txt') .then(open) .then(read) .then(close) .then(finished, catchall);Monday, March 11, 13

AUSFÜHRUNG

$ node promises2.js Hello World

File Handle closed

Monday, March 11, 13

JETZT HABT IHR’S GESCHAFFT

Monday, March 11, 13

FRAGEN?

Monday, March 11, 13

KONTAKT

Sebastian Springersebastian.springer@mayflower.de

Mayflower GmbHMannhardtstr. 680538 MünchenDeutschland

@basti_springer

https://github.com/sspringer82

Monday, March 11, 13

OHNE PROMISES

Monday, March 11, 13

OHNE PROMISES

Monday, March 11, 13

PROMISES

Monday, March 11, 13

PROMISES

Monday, March 11, 13

PROMISES

Monday, March 11, 13

PROMISES

Monday, March 11, 13

top related