node.js: the what, the how and the when
DESCRIPTION
Presented live at FITC Amsterdam 2014 on Feb 24-25, 2014 More details can be found at www.FITC.ca Node.js: The What, The How and The When with Richard NieuwenhuisTRANSCRIPT
Node.jsAwesome, Lightweight, JavaScript, High Performance
Scan de QR code or go to the link and get more information about this talk and answer “pub-quiz” questions to win prices (Booz ;-))
qr.net/fitc2014
WHO AM I?
• Richard Nieuwenhuis
• 32 years old
• MediaMonks
• 7 years a Monk
• Lead of Operations / Head of development
A nice show reel (Containing a lot of NodeJS stuff)
Overview• What is Node.js
• Some small examples
• Asynchrony here, asynchrony there
• Some (popular) Node.js modules
• Socket.io
• High performance examples
• Some tips & tricks
When and by whom?• First made public in 2009
• Ryan Lienhart Dahl
• Currently at version 0.10.25*
• “Why is a progress bar so difficult?”
• “Why the heck are we polling???”
• This sheet was created 17-2-2014
What nodejs.org says• “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.”
In short how many people see it
• Server side JavaScript!
High Level Component overview
Node.jsEvent Loop
(Libuv)
V8
Where to begin?
• Download & Install Node.js• Use your favorite IDE
• Node.js API/Modules:• Built-in• Sort of API’s which expose Node functions• Allows the Node.js community to extend Node.js• Super lightweight
• Add-ons• Quite a big community• The NPM (Node Package Manager)
Some Node.js APIs/Modules
• http
• Provides basic functions for creating a server and handling requests
• https
• For setting up a secured server
• assert
• For creating unit tests for your code (NodeTDD!)
• fs
• For doing stuff with the File System
Some Node.js APIs/Modules continued
• querystring
• For parsing the query string of a request
• url
• functions for parsing and resolving URL’s
• repl: Read-Eval-Print-Loop
• Good for debugging and testing
Let’s build something simple
• Simple server
• Every “Hello World” Example starts with this.
• Read the files of a folder.
• Print the file names in the browser in sorted fashion.
• PS. Examples show Node specifics and are to illustrate points and are by no means “elegant, save” etc :-)
Create our own module: sorterservice.js
function sortFileNames(fileNames){return fileNames.sort();
}
exports.sortFileNames = sortFileNames;
- a module can be a single file
- a module can be a folder
- exports is a special object to define properties
- Can be any type: function, strings, etc
Requiring needed modules
//require the needed modules
var http = require('http');
var fs = require('fs');
var sorter = require('./sorterservice');
Create server and verify requests
http.createServer(function(req, res){ switch(req.method){ case 'POST':
console.log('This is a post request'); break;
case 'GET': switch(req.url){
case '/': readFileNames(res); break;
case '/showfiles‘:
readFileNames(res); break;
case '/favicon.ico‘: break;
} break; default:
res.setHeader('Content-Type', 'text/plain'); res.end("This method I simply do not know"); } }).listen(8888);
Let’s read the file names
function readFileNames(res){
var dirName = './files';
var html = '';
var fileNames = fs.readdirSync(dirName);
var sortedFileNames = sorter.sortFileNames(fileNames);
html += '<ol>';
for(var index in sortedFileNames){
html += '<li>' + sortedFileNames[index] + '</li>';
}
html += '</ol>';
sendFileNames(res, html);
}
One last thing & Does it work?
function sendFileNames(res, html){
res.setHeader('Content-Type', 'text/html');
res.end(html);
}
Two big things not OK hereWhich are also two important Node aspects
1) Error handling
2) A-synchronous architecture
Main problem 1
function readFileNames(res){
var dirName = './files';
var html = '';
var fileNames = [];
fileNames = fs.readdirSync(dirName);
var sortedFileNames = sorter.sortFileNames(fileNames);
html += '<ol>';
for(var index in sortedFileNames){
html += '<li>' + sortedFileNames[index] + '</li>';
}
html += '</ol>';
sendFileNames(res, html);
}
What did we see?
• The server crashed and Node stopped running
• A lot less forgiving than PHP for example
• Not OK during a super bowl commercial where millions of Dollars are spend ;-)
Tip: Look at the Node.js module forever
In this case a simple
if (fs.existsSync(dirName)){
fileNames = fs.readdirSync(dirName);
}
Would suffice….
• Defensive programming is super important in Node
• Verify everything!
• Valid user input
• Expect the unexpected (even if you expect otherwise)
• Act on any error that may occur (and log it)
• Have a process in place to restart node just to be sure (forever module)
“Problemo” numero dos
fs.readdirSync(dirName);
Node is a single threaded running process.
Synchronous development
• Blocking/Synchronous requests are bad
• It will “block” the continuation of your logic for the amount of time the blocking request is active (requesting a JSON file for example)
• On the server you basically have the same problems
• But it will affect all visitors immediately when one request is stalling
• Can ultimately lead to a crashing server
Synchronous developmenthttp.createServer(function(req, res){
switch(req.method){
case 'POST':
console.log('This is a post request');
break;
case 'GET':
//”Select *” all 200K users from the database
//Give it back to the response
}
}).listen(8888);
Continued
CPU
processData()
doQuery()Request
Pffff, I need to return 200K
rows?
Going to take me a while!
DB
Cpu to r2: Sorry, I am doing
nothing, but the DB is sooooo
slowww
Request 2
Cpu time
The Event Loop
CPU
processData()
Request
Pffff, I need to return 200K
rows?
Going to take me a while!
DB
CPU to r2: thanks man! I am
processing your request
Request 2
Take this event loop!: doQuery(cb)
E loop
callback
A-Synchronous Node development
A lot of Node functions have a-synchronous versions.
fs.readdir(dirName, function(err, data){ if (err){
console.log(); }
var sortedFileNames = sorter.sortFileNames(data);
//The other code
---------------------------
http.createServer(function(req, res){……
A-Synchronous Node development
• A-synchronize as much as possible to keep the main process as “free” as possible.
• Much more necessary when it is a high-performance environment
• It is not the holy grail! Keep the Big O in mind: for (var x = 0; x < 25.5Billion; x++)
• Sequencing & parallel
• Can become quite messy and unreadable
A highly unlikely hypothetical situation
• Read the files from Dir A
• Merge the content of all files of Dir A into one file
• Read the files from Dir B
• Append the content of step 1 to all files in Dir B
• Store these results in the Database
Would look something like this
aSynReadDir('A/', function(files) {
mergeFiles(files, function(fileContents) {
aSynReadDir('B/', function(files) {appendFiles(fileContents, files, function(appendedFiles) {
insertIntoDatabase(appendedFiles, function() {});
});});
});});
Useful Node Modules: Socket.io
• Latest browsers support Web sockets
• IE10+
• Chrome
• FireFox
• “Weirdly” on Android only starting from 4.4…
• Socket.io leverages the Web socket technology for bi-directional communication between clients & servers:
• With degradability in place for the “older” browsers!
Socket.io continued
• Very nice for real time applications with a lot of concurrent users.
• Browser based games where you mobile is the controller
• Second screen applications
• Updating the client:
• Chat
• Real time statistics
• News updates
• Etc
Small example (Server)
var server = http.createServer(function(req, res){
//code here
});
var io = socketio.listen(server);
function sendRandomMessage(){
var index = Math.floor((Math.random()*4));
io.sockets.send(words[index]);
}
Small example (Client)
var socket = io.connect();
socket.on('message', function (message) {
console.log(‘I received the message ' + message);
var m = document.createElement('p');
m.innerText = message;
document.getElementById('text').appendChild(m);
});
Event Listener
socket.on('message', function (message)……
socket.emit(‘fired’, {message: yep, you are fired});
Other Useful Node Modules "dependencies": {
"express": "3.4.7", // Web Framework "express-validator": "1.0.1", "request": "2.25.0", // "redis": "0.10.0", //Redis: High performance in memory DB "hiredis": "0.1.16", // To make Redis even faster with C written stuff "redis-sentinel": "0.0.5", // Redis failover "http-auth": "*", //for authentication "openid": "0.5.5", //Open ID client "statsd-client": "*", //NodeJS deamon for logging request statistics "facebook-node-sdk": "0.2.0", "librato-metrics": "0.0.7", "statsd-client": "0.0.15" }
ADIDAS NITROCHARGE
CaseVide
o
An interactive cinematic experience using your mobile phone as a controller.Produced for DDB & Tribal
KLMCLAIM YOUR PLACE IN SPACE
CaseVide
o
Are you ready to win the ultimate journey of inspiration? Claim your spot in spaceProduced for DDB & Tribal Amsterdam
THE VOICE OF HOLLAND
CaseVide
o
Talpa
This season you can be a coach at home. Show your coaching qualities with The Voice of Holland Thuiscoach app.