31
Node.js Introducing @jamescarr

Introduction to nodejs

Embed Size (px)

Citation preview

Node.jsIntroducing

@jamescarr

It is no secret I think Node.js is the future in web development, and today I will tell you why.

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.

In a Nutshell

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

Some of my Favorite Modules

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

WebWorkersDemo: Finding Perfect Numbers

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.

Questions?