Slide 1

Slide 1 text

Intro to By Tim Caswell

Slide 2

Slide 2 text

About Me Long time Node.js contributor. Created howtonode.org. Spoken at over a dozen JavaScript and node.js conferences around the world. Started over a hundred open source projects on github. I love teaching programming and new tech! @creationix

Slide 3

Slide 3 text

What is Node.js? Node.js is a platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non- blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

Slide 4

Slide 4 text

What is Node.js? Node is the scripting interface to your operating system. It’s especially useful for anything that involves heavy I/O It’s built using a fast JavaScript engine bound to an efficient event-loop library.

Slide 5

Slide 5 text

Event Loop Performance Nginx is single-threaded, but uses non-blocking I/O

Slide 6

Slide 6 text

Event Loop Memory Usage Apache spawns thread per connection, wasting memory.

Slide 7

Slide 7 text

I/O Latency L1: 3 cycles L2: 14 cycles RAM: 250 cycles DISK: 41,000,000 cycles NETWORK: 240,000,000 cycles

Slide 8

Slide 8 text

I/O Latency L1: 3 cycles L2: 14 cycles RAM: 250 cycles DISK: 41,000,000 cycles NETWORK: 240,000,000 cycles

Slide 9

Slide 9 text

I/O Latency (In Human Terms) L1: Grabbing a paper from your desk. (3 seconds) L2: Getting a book from the shelf across the room. (14 seconds) RAM: Walking across the office. (4 minutes) DISK: Roaming the Earth for 16 months! NETWORK: 7 year journey.

Slide 10

Slide 10 text

Waiting Room Analogy Blocking vs non-blocking queues.

Slide 11

Slide 11 text

Creating a TCP Server // Load the built-in tcp/socket library. var net = require('net'); // Create a plain socket server that echoes input. var server = net.createServer(function (socket) { socket.write('Echo server\r\n'); socket.pipe(socket); }); // Bind and listen on a TCP port. server.listen(1337, '127.0.0.1');

Slide 12

Slide 12 text

Creating an HTTP Server var http = require('http'); // Create a server instance that accepts http connections var server = http.createServer(function (req, res) { // Respond to every request with the same message. res.writeHead(200, { 'Content-Type': 'text/plain', 'Content-Length': 12 }); res.end('Hello World\n'); }); // Start the server listening on a TCP port. server.listen(1337, '127.0.0.1');

Slide 13

Slide 13 text

Working with Child Process var spawn = require('child_process').spawn; var ls = spawn('ls', ['-lh', '/usr']); ls.stdout.on('data', function (data) { console.log('stdout: ' + data); }); ls.stderr.on('data', function (data) { console.log('stderr: ' + data); }); ls.on('close', function (code) { console.log('child process exited with code ' + code) });

Slide 14

Slide 14 text

Buffered File I/O var fs = require('fs'); // Buffered file reading fs.readFile('/etc/passwd', function (err, data) { if (err) throw err; console.log(data); }); // Buffered file writing fs.writeFile('message.txt', 'Hello Node', function (err) { if (err) throw err; console.log('It\'s saved!'); });

Slide 15

Slide 15 text

Streaming File and TTY I/O // Simple `cat` implementation var input = fs.createReadStream("input.txt"); input.pipe(process.stdout); // Redirecting stdin to a file var output = fs.createWriteStream("output.txt"); process.stdin.pipe(output); process.stdin.resume();

Slide 16

Slide 16 text

Streaming File Events var input = fs.createReadStream("myfile.dat"); input.on("data", function (chunk) { console.log("data", chunk); }); input.on("end", function () { console.log("end"); }); input.on("error", function (err) { console.error(err.stack); });

Slide 17

Slide 17 text

Timers in Node.JS // Delayed Hello World using a timeout. setTimeout(function () { console.log("World"); }, 1000); console.log("Hello");

Slide 18

Slide 18 text

Interactive Prompt var readline = require('readline'); var rl = readline.createInterface({ input: process.stdin, output: process.stdout }); rl.question("What is your name? ", function(name) { console.log("hello", name); rl.close(); });

Slide 19

Slide 19 text

Basic Node Concepts Single-purpose modules Async Functions with Callbacks Event Emitters Streams Function Closures and Objects

Slide 20

Slide 20 text

Single-Purpose Modules Do one thing and do it well. Many modules export a single function or API endpoint.

Slide 21

Slide 21 text

Single-Purpose Module // log.js module.exports = function (app) { // Do server setup stuff here. return function (request, respond) { // Do request setup stuff here. app(request, function (code, headers, body) { // Do response hooks here. console.log(request.method, request.url, code); }); }; };

Slide 22

Slide 22 text

Single-Purpose Module // server.js var app = function (req, res) { res(200, { "Content-Type": "text/plain" }, "Hello World\n"); }; // Use the logging module app = require('./log.js')(app);

Slide 23

Slide 23 text

Async Functions / Callbacks The non-blocking version of a function call. Eventually outputs a value (return) or fails with an error (throw) fn(arg1, arg2, function (err, res1, res2) { ... })

Slide 24

Slide 24 text

Async Function Example var fs = require('fs'); // Buffered file reading fs.readFile('/etc/passwd', function (err, data) { if (err) throw err; console.log(data); }); // Buffered file writing fs.writeFile('message.txt', 'Hello Node', function (err) { if (err) throw err; console.log('It\'s saved!'); });

Slide 25

Slide 25 text

Wrapping Async Functions function readCaps(path, callback) { fs.readFile(path, "utf8", function (err, text) { if (err) return callback(err); callback(null, text.toUpperCase()); }); }

Slide 26

Slide 26 text

Doing Serial Actions function getUserFile(userID, callback) { // Start an async database lookup getFilename(userID, onGetFilename); function onGetFilename(err, filename) { if (err) return callback(err); // Start an async file operation readFile(filename, onReadFile); } function onReadFile(err, data) { if (err) return callback(err); callback(null, filename, data); } }

Slide 27

Slide 27 text

Doing Serial Actions // Or for simple cases, use nested callbacks. function getUserFile(userID, callback) { getFilename(userID, function (err, filename) { if (err) return callback(err); readFile(filename, function (err, data) { if (err) return callback(err); callback(null, filename, data); }); }); }

Slide 28

Slide 28 text

Doing Parallel Actions function getPageData(pageID, authorId, callback) { var page, author; loadPage(pageId, function (err, result) { if (err) return callback(err); page = result; if (author) callback(null, page, author); }); loadAuthor(authorID, function (err, result) { if (err) return callback(err); author = result; if (page) callback(null, page, author); }); }

Slide 29

Slide 29 text

Event Emitter s Represent events that may happen zero or more times. A single emitter may emit different types of events. The “error” event is special and must be handled or it will crash. Usually represent human interaction or stream events.

Slide 30

Slide 30 text

Readline Event Example rl.on('line', function(line) { switch(line.trim()) { case 'hello': console.log('world!'); break; default: console.log('Unexpected `' + line.trim() + '`'); break; } rl.prompt(); }).on('close', function() { console.log('Have a great day!'); process.exit(0); });

Slide 31

Slide 31 text

Making You Own Emitter // Creating your own EventEmitters is easy var EventEmitter = require('events').EventEmitter; var bob = new EventEmitter(); bob.on("speak", function (message) { console.log("Bob says " + message); }); bob.emit("speak", "Hello World");

Slide 32

Slide 32 text

Creating Custom Emitters // Create your own class that inherits from EventEmitter function JoyStick(id) { // Call the super constructor EventEmitter.call(this); // Do your own custom logic too this.openDevice(id); // ... } Joystick.prototype.__proto__ = EventEmitter.prototype;

Slide 33

Slide 33 text

Streams Streams are a special EventEmitter with a predefined interface. Streams represent a stream of data, usually through a network socket or file I/O. Streams can be piped together like Unix commands.

Slide 34

Slide 34 text

Closures and Objects Understanding how functions and closures work in JavaScript is essential to understanding Streams represent a stream of data, usually through a network socket or file I/O. Streams can be piped together like Unix commands.

Slide 35

Slide 35 text

Local Variables // Let's create some local variables in the top scope var name = "Tim Caswell"; var age = 30; var isProgrammer = true; var likesJavaScript = true; // Test to see if the two variables are the same. isProgrammer === likesJavaScript; //-> true

Slide 36

Slide 36 text

Global Variables var name = "Tim Caswell"; var age = 30; var isProgrammer = true; // Oops we forgot a var statement! likesJavaScript = true;

Slide 37

Slide 37 text

Objects and Inheritance // Create a parent object var tim = { name: "Tim Caswell", age: 28, isProgrammer: true, likesJavaScript: true } // Create a child object var jack = Object.create(tim); // Override some properties locally jack.name = "Jack Caswell"; jack.age = 4; // Look up stuff through the prototype chain jack.likesJavaScript;

Slide 38

Slide 38 text

Objects and Inheritance

Slide 39

Slide 39 text

Closure Objects function makeClosure(name) { return function () { return name; }; } var description1 = makeClosure("Cloe the Closure"); var description2 = makeClosure("Albert the Awesome"); console.log(description1()); console.log(description2());

Slide 40

Slide 40 text

Closure Objects

Slide 41

Slide 41 text

Shared Functions var Lane = { name: "Lane the Lambda", description: function () { return this.name; } }; var description = Lane.description; var Fred = { description: Lane.description, name: "Fred the Functor" }; // Call the function from four different scopes console.log(Lane.description()); console.log(Fred.description()); console.log(description()); console.log(description.call({ name: "Zed the Zetabyte" }));

Slide 42

Slide 42 text

Shared Functions

Slide 43

Slide 43 text

Classical Constructors function Rectangle(width, height) { this.width = width; this.height = height; } Rectangle.prototype.getArea = function () { return this.width * this.height; }; Rectangle.prototype.getPerimeter = function () { return 2 * (this.width + this.height); };

Slide 44

Slide 44 text

Classical Constructors function Square(side) { this.width = side; this.height = side; } // Make Square inherit from Rectangle Square.prototype.__proto__ = Rectangle.prototype; // Override a method Square.prototype.getPerimeter = function () { return this.width * 4; };

Slide 45

Slide 45 text

Classical Constructors // Add a nice toString method to the parent class Rectangle.prototype.toString = function toString() { return this.constructor.name + " a=" + this.getArea() + " p=" + this.getPerimeter(); }; var rect = new Rectangle(6, 4); var sqr = new Square(5); console.log(rect.toString()) console.log(sqr.toString())

Slide 46

Slide 46 text

Classical Constructors

Slide 47

Slide 47 text

Pure Prototypal Objects var Rectangle = { name: "Rectangle", getArea: function getArea() { return this.width * this.height; }, getPerimeter: function getPerimeter() { return 2 * (this.width + this.height); }, toString: function toString() { return this.name + " a=" + this.getArea() + " p=" + this.getPerimeter(); } };

Slide 48

Slide 48 text

Pure Prototypal Objects var Square = Object.create(Rectangle); Square.name = "Square"; Square.getArea = function getArea() { return this.width * this.width; }; Square.getPerimeter = function getPerimeter() { return this.width * 4; };

Slide 49

Slide 49 text

Pure Prototypal Objects var rect = Object.create(Rectangle); rect.width = 6; rect.height = 4; var square = Object.create(Square); square.width = 5; console.log(rect.toString()); console.log(square.toString());

Slide 50

Slide 50 text

Pure Prototypal Objects

Slide 51

Slide 51 text

Object Factories function Controller(model, view) { view.update(model.value); return { up: function onUp(evt) { model.value++; view.update(model.value); }, down: function onDown(evt) { model.value--; view.update(model.value); }, save: function onSave(evt) { model.save(); view.close(); } }; }

Slide 52

Slide 52 text

Object Factories var on = Controller( { // Inline a mock model value: 5, save: function save() { console.log("Saving value " + this.value); } }, { // Inline a mock view update: function update(newValue) { console.log("View now has " + newValue); }, close: function close() { console.log("Now hiding view"); } } ); setTimeout(on.up, 100); setTimeout(on.down, 200); setTimeout(on.save, 300);

Slide 53

Slide 53 text

Object Factories // Output View now has 5 View now has 6 View now has 5 Saving value 5 Now hiding view

Slide 54

Slide 54 text

Object Factories