On Github benjie / nodejs-workshop
By @Benjie
Get the latest stable version of Node from nodejs.org/download and install it.
Mac: brew install node
Linux: [sudo] tar zxf node-*.tar.gz --strip-components=1 -C /usr/local
$ uname -a # Linux .... i686 < 32bit or something64 < 64bit
Once installed, run node in the command line:
$ node > 1+2 3 > ^D
You may need to update your $PATH so it can find node
What is node?Create a folder somewhere for this workshop.
cd; mkdir node-workshop; cd !$
Add the following to a new file hello-world.js
console.log("Hello world!");
And then run it:
$ node hello-world.js Hello world! $
$ node > console.log("Hello world!"); Hello world! undefined > 1+2 3 > {}+{} '[object Object][object Object]' >
/* Variables */ var one = 1;
/* Objects */ var obj = {}; obj.property = one;
/* Arrays */ var arr = [one, obj];
/* Primitives */ var prims = [-1.3, "Str", true, null, undefined];
/* Buffers */ var b = new Buffer("Hello world!"); b.toString('base64'); /* or hex or utf8 or ... */
/* Undefined */ var v; if (v === undefined) { console.log("Careful"); }
/* typeof */ if (typeof v === 'undefined') { console.log("Good"); }
/* Accessing */ console.log(arr[1]['property']);
/* Concat */ console.log("Join " + val + " and " + 3.03); // Fix code colouring
/* Functions */ function myFunc(param) { console.log("Got: "+param); }
/* 1st class */ function seven(fn) { fn(7); }; seven(myFunc);
/* Anonymous */ seven(function(nr) { console.log(nr * nr); });
function Animal() {}
var a = new Animal();
Animal.prototype.getType = function() { return 'an animal'; }
Animal.prototype.announceSelf = function() { console.log("I am "+this.getType()); }
a.announceSelf(); // I am an animal
function Cat() {}
Cat.prototype = new Animal();
Cat.prototype.getType = function() { return 'a cat'; }
var c = new Cat(); c.announceSelf(); // I am a cat
var c2 = new Cat(); c2.getType = function(){ return 'a beautiful cat'; } c2.announceSelf(); // I am a beautiful cat
var c3po = new Cat(); c3po.getType = function(){ return 'a robotic cat'; } c3po.announceSelf(); // I am a robotic cat
c.announceSelf(); // I am a cat a.announceSelf(); // I am an animal
Source: http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/
Here are the options we have for dealing with this:
A programmer had a problem. He thought I know, I'll solve it with threads! . has Now problems. two he
— azeem (@azeem) June 4, 2014Source: http://blog.webfaction.com/2008/12/a-little-holiday-present-10000-reqssec-with-nginx-2/
"Pens down!"
Your code should quickly request work, optional callback.
var http = require('http'); function listener(request, response) {/* ... */} var server = http.createServer(listener /* <- callback */); server.listen(1337); /* <- request work */
Background thread pool handles work.
GET / HTTP/1.0
Node triggers callback when IO occurs/completes.
var request = new http.IncomingMessage(/* ... */); var response = new http.ServerResponse(/* ... */); listener(request, response);
Repeat
function listener(request, response) { response.end("Hello world!"); /* <- request work */ }
Comes with Node.js nowadays
Search: npm search graceful-fs
Install: npm install graceful-fs coffee-script
Install globally: [sudo] npm install -g nodemon
Installs to node_modules
Include: var fs = require('graceful-fs');
Uninstall: npm uninstall graceful-fs
Create a package.json interactively: npm init
Prevent accidental publishing to npm: "private":true
Install and save dependency: npm install --save express
Save by default: npm config set save true
Jump to documentation for a module: npm docs coffee-script
Define scripts:
"scripts": { "test": "echo All tests pass", "truth": "echo Node.js rocks", "start": "node index.js" }
Run tests: npm test
Run other scripts: npm run truth
Start the main app: npm start
Enter the following into server.js
var http = require('http'); function listener(request, response) { response.end("Hello world!"); } var server = http.createServer(listener); server.listen(1337);
Then run it:
$ node server.js
Let's share our own source code with the world:
var http = require('http'); var fs = require('fs'); function listener(request, response) { function send(err, contents) { if (err) { console.error(err); // DON'T DO THIS IN PRODUCTION response.writeHead(500); response.end("ERROR"); } else { response.end(contents); } } fs.readFile(require.main.filename, send); } var server = http.createServer(listener); server.listen(1337);
But this means if we have a traffic surge we'll get EMFILE - too many files open.
Let's gracefully share our own source code with the world:
var http = require('http'); //var fs = require('fs'); var fs = require('graceful-fs'); // npm install graceful-fs function listener(request, response) { function send(err, contents) { if (err) { console.error(err); // DON'T DO THIS IN PRODUCTION response.writeHead(500); response.end("ERROR"); } else { response.end(contents); } } fs.readFile(require.main.filename, send); } var server = http.createServer(listener); server.listen(1337);
But this means we have to open the file over and over again, despite it's relatively small size
Save server.js as server.preloading.js
var http = require('http'); var fs = require('graceful-fs'); var fileContents; function listener(request, response) { response.end(fileContents); } var server = http.createServer(listener); function read(err, contents) { if (err) { console.error(err); process.exit(1); } else { fileContents = contents; server.listen(1337); } } fs.readFile(require.main.filename, read);
npm install -g node-inspector
node --debug server.js
node-inspector &
http://127.0.0.1:8080/debug?port=5858 in Chrome
Select server.js on the left
Add a breakpoint to response.send(contents);
Load your server (http://localhost:1337/)
Now edit the code!
Own closure
exports
module.exports
/* server.js */ var http = require('http'); var myModule = require('./my-module'); var server = http.createServer( myModule.serveSource ); server.listen(1337);
/* my-module.js */ var fs = require('graceful-fs'); function listener(request, response) { function send(err, contents) { if (err) { console.error(err); response.writeHead(500); response.end("ERROR"); } else { response.end(contents); } } fs.readFile( require.main.filename, send ); } exports.serveSource = listener;