Intro to NodeJSMatthew Eernisse
Toster Conference 2011-10-282001
Who am I?
Matthew EernisseWork at Yammer@mde on Twitter
JavaScript at YammerBrowsers (yammer.com Web UI)
Adobe AIR Desktop
V8 in Rails via TheRubyRacer
NodeJS
•
•
•
•
NodeJS:“Evented I/O for V8 JavaScript”
http://nodejs.org/
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n');
}).listen(1337, "127.0.0.1");
console.log( 'Server running at http://127.0.0.1:1337/');
Hello, NodeJS
Server JS
Netscape Enterprise Server (OG SSJS)
Microsoft IIS
Helma (now RingoJS)
Whitebeam
Zimki
Jaxer
Perservere
Nitro
Google App Engine
CouchDB
NodeJS
•
•
•
•
•
•
•
•
•
•
•
History of SSJS
Why NodeJS now?Steve Yegge’s NBL post, 2007-02-10
Competition in JavaScriptinterpreters
Simple, POSIX API
Non-blocking from the ground up; soare the libraries
•
•
•
•
What is NodeJS good for?Lightweight, networked apps
Proxies with embedded logic
Streaming data
System scripting
Evented realtime apps
•••••
NodeJS is not good at complexdatabase-backed Web
applications.You can use Rails.
Geddy Web framework:https://github.com/mde/geddy
NodeJS at YammerDevelopment proxy
Jake for build and test(https://github.com/mde/jake)
Upload service for files and images (Geddy v0.2)
Browserless tests with FooUnit (https://github.com/foobarfighter/foounit)
Realtime, collaborative document-editing service
•
•
•
•
•
Jake build toolhttps://github.com/mde/jake•
Similar to Make or Rake
Tasks, prerequisites
File tasks, directory tasks
Namespaces
PackageTasks
Async task execution
Just executable JavaScript
•
•
•
•
•
•
•
desc('This is the default task.');task('default', function () { console.log('This is the default task.'); console.dir(arguments);});
namespace('foo', function () { desc('This the foo:bar task'); task('bar', function () { console.log('doing foo:bar task'); console.dir(arguments); });
desc('This the foo:baz task'); task('baz', ['default', 'foo:bar'], function () { console.log('doing foo:baz task'); console.dir(arguments); });
});
desc('This is an asynchronous task.');task('async', function () { setTimeout(function () { console.log('Hooray!'); complete(); }, 1000);}, true);
desc('Calls the foo:bar task and its dependencies.');task('invokeFooBar', function () { // Calls foo:bar and its deps jake.Task['foo:bar'].invoke(); // Does nothing jake.Task['foo:bar'].invoke(); // Only re-runs foo:bar, but not its dependencies jake.Task['foo:bar'].reenable(); jake.Task['foo:bar'].invoke();});
var fs = require('fs') , pkg = JSON.parse( fs.readFileSync('package.json').toString()) , version = pkg.version
var t = new jake.PackageTask('jake', 'v' + version, function () { var fileList = [ 'Makefile' , 'Jakefile' , 'README.md' , 'package.json' , 'lib/*' , 'bin/*' , 'tests/*' ]; this.packageFiles.include(fileList); this.needTarGz = true; this.needTarBz2 = true;});
Remote upload serviceMinimal v1 in prod, Nov. 2010
Redis, CORS XHR-push or JSONP for upload-progressreporting
Onboard thumbnailing, remote services for video anddocument post-processing
Three-machine cluster, not under a heavy load
Large file sizes (e.g., 1.5GB)
•
•
•
•
•
Realtime, collaborative doc-editing service
In beta Oct. 21, 2011 (last week)
NodeJS, Socket.io, PostgreSQL
No production metrics yet for perf/scalability
•
•
•
Coding JS for Node
Awesome:JavaScript is simple and
super-flexible
Horrible:JavaScript is simple and
super-flexible
Even shelling out is async?
“1, 3, 2, go!” development
Evented and callback-based control-flow
A familiar model?
Async patterns and libraries
•••••
Asynchronous code
var asyncFun = function () { console.log('1'); setTimeout(function () { console.log('3'); }, 0); console.log('2'); console.log('go!');};
1, 3, 2, go!
var fetchAndUpdate = function (params) { var items = db.fetch(someQuery); for (var i = 0, ii = items.length; i++) { item.update(params); } return true;};
Sync fetch-and-update
var fetchAndUpdate = function (params, callback) { db.fetch(someQuery, function (items) { var count = 0; for (var i = 0, ii = items.length; i++) { item.update(params, function () { count++; if (count == ii) { callback(true); } }); } });};
Async fetch-and-update
jQuery.ajax({ url: '/foo/bar.json', success: function () { alert('yay!'); }});
jQuery('#foo').bind('click', function (e) { // Do some stuff});
Is this familiar?
Async patterns and libs
Queue
Promise/deferred
In-flight registry
•••
var asyncQueueHandler = function (items, handler, callback) { var queue = items.slice() , handleNextItem = function () { var next = queue.pop(); if (next) { handler(next, function () { handleNextItem(); }); } else { callback(); } }; handleNextItem();};
Queue
var p = new yammer.util.Promise();p.when('foo', 'bar', 'baz').then( function () { console.log('done!');});p.satisfy('foo');p.satisfy('bar');p.satisfy('baz');
p.then(function () { console.log('still done!');});
Promise
NodeJS in production
Third-party modules still may changerapidly
Maintain forks, push back patches whereappropriate
•
•
App dependencies
Callbacks in global scope have no stack
Assume you’re fucked
Default condition is a preemptible error
In-flight registry with uncaughtExceptionhandler
••••
Debugging NodeJS
FlightCheckhttps://github.com/mde/flight_check•
Add items to in-flight registry
Per-item timeout
Configurable polling-interval
Define a timeout-handler
•
•
•
•
var FlightCheck = require('flight_check').FlightCheck;var handler = function (req, resp) { var checker = new FlightCheck(function (key) { resp.writeHead(500); resp.end('Oops, something bad happened.'); }); checker.add('foo', 10000); doFoo(req, function (result) { if (result.ok) { checker.clear('foo'); // Do some other stuff resp.writeHead(200); resp.end('Hooray!'); } });};
process.on('uncaughtException', function (err) { // Do some kind of logging});
In-flight registry
Measure everything
Log everything
https://github.com/mikejihbe/metrics
•••
Visibility, metrics
Communicative, consultative dev
Ask what is expected
Play nicely with others
•••
Ops
The future?JS interpreters will keep improving
JS language will keep improving (see:JS.next)
NodeJS ecosystem will grow and mature
Try NodeJS, you’ll like it
••
••
Matthew Eernissehttp://twitter.com/mde
Yammer Developer Centerhttp://developer.yammer.com/