Upload
james-carr
View
1.235
Download
1
Embed Size (px)
Citation preview
Node.js is ...
Fast Event DrivenNon-Blocking Implemented in V8Serverside Awesome
(But not just for servers, more later)
Fun to code in, easy to use.
def contents = new File('foo.txt').getText()
println contents
println 'something else' All of these events happen in sequence
Most operations in other languages are blocking
Node.js on the other hand utilizes callbacks to make operations more asynchronous
fs.readFile('foo.txt', function(err, contents){ console.log(contents);});
console.log('something else')“something else” will get executed while the file is being read.
Code like this can allow the program to return to the event loop right away and do other tasks.
The Traditional “Hello World” App
var http = require('http');
http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.write('Hello World.'); res.end();}).listen(80, function(){ console.log('server running on port 80');}); /* server started */
Getting Startedhttp://nodejs.orgAPI Documentation: http://nodejs.org/api.htmlIRC: irc.freenode.org #node.jshttp://github.com/ry/node/wikiGoogle Groups: http://groups.google.com/group/nodejs
$ git clone http://github.com/ry/node.git$ cd node$ ./configure && make && sudo make install
Installation
It's really that easy given you're on linux, OSX, or cygwin (although cygwin can sometimes be a little flakey).
Sorry, no windows support (yet).
Not too keen on using the bleeding edge?
$ git clone http://github.com/ry/node.git$ cd node$ ./configure && make && sudo make install
$ wget http://nodejs.org/dist/node-v0.2.4.tar.gz$ tar zxvf node-v0.2.4.tar.gz$ cd node$ ./configure && make && sudo make install
The Traditional “Hello World” App
var http = require('http');
http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.write('Hello World.'); res.end();}).listen(80, function(){ console.log('server running on port 80');}); /* server started */
Now let's modularize this a bit...
var http = require('http'), greeter = require(__dirname + 'greeter');
http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end(greeter.greet('World');}).listen(80, function(){ console.log('server running on port 80');}); /* server started */
exports.greet = function (name) { return 'Hello ' + name + '.';}
greeter.js
In this example I've created a new module to be used from the main script. Modularization is a major part of writing any application so let's delve deeper into how node.js modules are constructed.
app.js
Common.js ModulesNode.js implements common.js 1.0 modules with some amount of flexibility.
Every script in node.js has a module global variable, which contains various details about the module:
id – an identifier for this module, usually the location on the file system
exports – an array of variables exported for use externally. Everything else is encapsulated within the script
parent – the module that included this module. undefined for the top level module
99.99% of the time module.exports is all you will use.
Everything not assigned to exports (or any other node.js global objects) is only visible within the scope of the module (Not unlike the revealing
module pattern in client side js)More Examples:
function sayGreeting(name) { return 'Hello ' + name + '.';}exports.greet = sayGreeting;
module.exports = { add: function(a,b){ return a+b; }, multiply: function(a,b){ return a * b}}
Here, sayGreeting is not visible outside of the module except through greet.
var math = require('math'), add = require('math').add;
math.add(2,2) == add(2,2);
More on require()Looks in require.paths to resolve modules
Add to it: require.paths.unshift(__dirname + '/lib');
(in case you didn't realize, __dirname is the dir of the current script)Can also be called asynchronously
require('fs', function(fs){ // do something with the fs module here.});
Exported variables can be referenced directly and even instantiated
var emitter = new(require('events').EventEmitter);
Events“Time is a sort of river of passing events, and strong is its current; no sooner is a thing brought to sight than it is swept by and another takes its place, and this too will be swept away.” - Marcus Aurelius
EventEmitter allows the firing and listening of events within node.js. Objects that allow attachment of event listeners use EventEmitter under the hood.
var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter();
emitter.on('pricechange', function(old, new){console.log(old + ' changed to ' + new);
});
emitter.emit('pricechange', 12.99, 10.99);emitter.emit('pricechange', 15.99, 17.99);
In Action
Keep In Mind...Event emitters don't interact with each other
var events = new(require('events').EventEmitter);var events2 = new(require('events').EventEmitter);
events2.on('test', function(msg){ console.log(msg);});
events.on('test', function(msg){ console.log(msg);});events.emit('test', 'some message');
Here the events2 callback will never get called. That is because the callback is assigned to a different EventEmitter instance.
EventEmitter is best used “mixed in” with an object to let clients respond to different events that happen
var EventEmitter = require('events').EventEmitter;
function User(name){ this.name = name}// This is one of many ways to inherit from another objectUser.prototype.__proto__ = EventEmitter.prototype
var user = new User('Jim');
user.on('login', function(){console.log('user ' + this.name + ' has logged in');
});
user.emit('login');
Events are really a great way to let clients use your module and respond to different events it might fire without having to be too concerned about the details.
Let's take a turn back towards modules. Sure, creating a module is easy, but how can you share modules with others?
Or take advantage of existing modules?
NPM NodePackageManager
Ruby has gem to install manage packages, node.js has npm
Install: https://github.com/isaacs/npm
http://npmjs.org
Simple install: curl http://npmjs.org/install.sh | sh
Browse packages: http://npm.mape.me
In addition to being a kick ass package management system it also makes it very easy to bundle dependencies with a project for deployment.
npm bundle ./vendor
Express.jsGet it: npm install express
Very simple and elegant routing syntax for building applications
Supports a variety of template engines out of the box: jade, haml.js, ejs.
http://expressjs.com
Commandline tool (express) to quickly create a skeletal project structure
var express = require('express'), app = express.createServer();
app.get('/users', function(req, res){res.render('users.jade', {
locals:{ users:[];}
});});
app.get('/user/:id', function(req, res){res.send('user ' + req.params.id);
});
app.listen(3000);
Express.js
Connect.jsMiddleware for building web applications and more specifically web application frameworks. Think of it as a framework's framework. ;)
(for example, express uses connect under the hood)
Need sessions, json-rpc, routing? Connect is for you!
https://github.com/senchalabs/connect
npm install connect
Connect addons: oauth, openid, etc
WebSocketsWebSockets have a lot of popularity in node.js due to the early adoption and ease of use
Two real contenders: websocket-server and socket.io
Websocket-server – implements the specs
Socket.IO – uses it's own non-spec API on top of websockets, but works with all sorts of fallback mechanisms using a client side library
http://socket.iohttps://github.com/miksago/node-websocket-server
npm install websocket-servernpm install socket.io
WebWorkersImplements the WebWorkers API as a mechanism for interprocess communication
Start up a script in a separate process, send and receive messages to it
https://github.com/pgriess/node-webworker https://github.com/cramforce/node-worker
ClusteringThe answer: node.js doesn't have any built in support for clustering
However, there is much work afoot that will help depending on your needs.
node-event-stream - https://github.com/miksago/node-eventstream Uses websockets to replicated events between serversnode-amqp-events –
uses amqp to replicate events between servers
There also many modules for storing sessions in various NoSQL databases to make them appear replicated across server instances
WarningAPI is subject to change
In fact examples you find online are probably outdated. The channel and mailing list can help.