Documente Academic
Documente Profesional
Documente Cultură
@mbleigh
Saturday, April 17, 2010
present.ly
Saturday, April 17, 2010
Whats Node?
Runs on Googles V8
Saturday, April 17, 2010
var sys = require('sys'), http = require('http'); http.createServer(function (req, res) { setTimeout(function () { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }, 2000); }).listen(8000); sys.puts('Server running at http://127.0.0.1:8000/');
Supported By Node
RESTful DSL for Node webapps Cookies, sessions, caching, etc. expressjs.com
Saturday, April 17, 2010
require.paths.unshift('path/to/express/lib') require('express') get('/', function(){ this.redirect('/hello/world') }) get('/hello/world', function(){ return 'Hello World' }) run()
Why Node?
Generally Speedy
> summary(node1$ttime) Min. 1st Qu. Median 0.0000 0.0000 1.0000 > summary(thin1$ttime) Min. 1st Qu. Median 0.000 1.000 1.000
Mean 0.7437
3rd Qu. Max. 1.0000 106.0000 Max. 74.000 Max. 88.00 Max. 39.00
> summary(narwhal1$ttime) Min. 1st Qu. Median Mean 3rd Qu. 15.00 22.00 23.00 23.74 24.00 > summary(v8cgi1$ttime) Min. 1st Qu. Median 12.00 13.00 13.00 Mean 3rd Qu. 14.49 18.00
four.livejournal.com/1019177.html
Great at Concurrency
Saturday, April 17, 2010
Asynchronous Everything
Saturday, April 17, 2010
bit.ly/nodejs-fstream
function upload_file(req, res) { req.setBodyEncoding('binary'); var stream = new multipart.Stream(req); stream.addListener('part', function(part) { part.addListener('body', function(chunk) { var progress = (stream.bytesReceived / stream.bytesTotal * 100).toFixed(2); var mb = (stream.bytesTotal / 1024 / 1024).toFixed(1); sys.print("Uploading "+mb+"mb ("+progress+"%)\015"); // chunk could be appended to a file if the uploaded file needs to be saved }); }); stream.addListener('complete', function() { res.sendHeader(200, {'Content-Type': 'text/plain'}); res.sendBody('Thanks for playing!'); res.finish(); sys.puts("\n=> Done"); }); }
Why Ruby?
When to Node
Real-Time Applications
Saturday, April 17, 2010
WebSockets
Persistent server connections Part of HTML5 True real-time for web apps Deprecate to Flash Sockets
Saturday, April 17, 2010
Why Real-Time?
Better on your server Better for your user You need more buzzwords
Saturday, April 17, 2010
var socket = new WebSocket("ws://www.websocket.org"); socket.onopen = function(evt) { alert("Open."); }; socket.onmessage = function(evt) { alert(evt.data); }; socket.onclose = function(evt) { alert("Closed."); }; socket.send("Hello Web Socket!"); socket.close();
You already write your client Just an extension of that Same interface throughout
Saturday, April 17, 2010
node.websocket.js
github.com/guille/node.websocket.js/
Socket.IO
Multi-transport socket for Node Comes with client JS library For production usage
Saturday, April 17, 2010
github.com/rosepad/socket.io-node
node.ws.js
Minimal Node WebSocket server Talk to your browser clients Javascript all the way down Mostly for experimentation github.com/ncr/node.ws.js
Saturday, April 17, 2010
Example
class User < ActiveRecord::Base # Include default devise modules. Others available are: # :token_authenticatable, :lockable and :timeoutable devise :database_authenticatable, :registerable, :rememberable, :validatable # Setup accessible (or protected) attributes for your model attr_accessible :email, :password, :password_confirmation def follow(other_user) Red.sadd "user:#{other_user.id}:followers", self.id Red.sadd "user:#{self.id}:follows", other_user.id end def follower_ids Red.smembers "user:#{self.id}:followers" end def follow_ids Red.smembers "user:#{self.id}:follows" end def update(text) (follower_ids + [self.id]).each do |uid| Red.lpush "user:#{uid}:timeline", text Red.lpush "user:#{uid}:updates", text Red.publish "user:#{uid}:timeline", text end end end
def update(text) (follower_ids + [self.id]).each do |uid| Red.lpush "user:#{uid}:timeline", text Red.lpush "user:#{uid}:updates", text Red.publish "user:#{uid}:timeline", text end end
var sys = require("sys"), ws = require("./ws"), redis = require("./redis-client"); var pubsub = redis.createClient(); pubsub.stream.addListener('connect', function() { pubsub.subscribeTo("user:*:timeline", function(channel, data) { var uid = channel.toString().split(':')[1]; if (clients[uid]) { sys.debug("Writing " + data + " to " + uid) clients[uid].write(data); } else { sys.debug("User " + clients[uid] + " is not connected."); } }); }); ws.createServer(function (websocket) { var user_id = null; var websocket = websocket; websocket.addListener("connect", function (resource) { user_id = resource.match(/timeline\/([0-9]+)$/i)[1] clients[user_id] = websocket; }).addListener("close", function() { sys.debug("User " + user_id + " disconnected.") }); }).listen(8080);
ws.createServer(function (websocket) { var user_id = null; var websocket = websocket; websocket.addListener("connect", function (resource) { user_id = resource.match(/timeline\/([0-9]+)$/i)[1] clients[user_id] = websocket; }).addListener("close", function() { sys.debug("User " + user_id + " disconnected.") }); }).listen(8080);
pubsub.stream.addListener('connect', function() { pubsub.subscribeTo("user:*:timeline", function(channel, data) { var uid = channel.toString().split(':')[1]; if (clients[uid]) { sys.debug("Writing " + data + " to " + uid) clients[uid].write(data); } else { sys.debug("User " + clients[uid] + " is not connected."); } }); });
if ("WebSocket" in window) { var ws = new WebSocket("ws://127.0.0.1:8080/timeline/" + current_user); ws.onmessage = function(evt) { $('ul.timeline').prepend("<li>" + evt.data + "</li>"); } }
Asynchronous Applications
Saturday, April 17, 2010
Push APIs
Want to notify API subscribers in
real-time
File Transcoding
Online Gaming
Ephemeral Peer-to-Peer
Saturday, April 17, 2010
Wrapping up...
howtonode.org
EventMachine
Cramp
Questions?