Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RESTful Services in Node.JS

RESTful Services in Node.JS

Building services with Express. Best practices for avoiding callback hell. Sharing templates between client-side & server-side JavaScript code.

Nebraska JS

January 03, 2013
Tweet

More Decks by Nebraska JS

Other Decks in Programming

Transcript

  1. History • Invented in 2009 by Ryan Dahl • Currently

    maintained by Joyent Thursday, January 3, 13
  2. ‣JavaScript on the Server ‣Asynchronous I/O ‣Event Driven ‣Built on

    top of Google’s V8 What is node.js? Thursday, January 3, 13
  3. Node.js Pros/Cons • Write code in a single language for

    backend/ frontend • JavaScript is fun! • Can share frontend/backend code • No context switch between frontend/backend code • Non-blocking I/O is different and can be hard • Callback hell - hard to maintain code • missing/immature libraries Pros Cons Thursday, January 3, 13
  4. • Install binary • Build • homebrew (OS X) •

    brew install node Installing Node.js Thursday, January 3, 13
  5. Accessing Other Files var User = function (firstName, lastName) {

    this.firstName = firstName || ''; this.lastName = lastName || ''; }; User.prototype.getName = function () { return this.firstName + ' ' + this.lastName; }; module.exports = User; var User = require("./user"); var user = new User("Big", "Deal"); console.log("Hello, ", user.getName()); user.js hello.js Thursday, January 3, 13
  6. • Comes with Node.js • Install packages / utilities/command line

    tools NPM npm install PACKAGE npm install -g PACKAGE ./node_modules /usr/local Thursday, January 3, 13
  7. package.json { "name": "sample-app", "version": "0.0.1", "private": true, "scripts": {

    "start": "node app" }, "dependencies": { "express": "3.0.5", "less-middleware": "*", "hbs": "~2.0.1" } } npm install Thursday, January 3, 13
  8. Simple Express Server var express = require('express'); var app =

    express(); app.get('/', function (req, res) { res.send("Hello, World"); }); app.listen(3000); Thursday, January 3, 13
  9. Simple Middleware var express = require("express"), fs = require('fs'); var

    app = express(); app.get('/', function (req, res) { res.send("Hello, World"); }); var middleware = function (req, res, next) { // do something important // or don't. // i'm a comment, not a cop fs.readFile(__dirname + '/name.txt', function (err, data) { req.name = data; next(); }); }; app.get('/foo', middleware, function (req, res) { res.send("Hello, " + req.name + " from the route!"); }); app.use(function (req, res) { res.writeHead(200, { "Content-Type": "text/plain" }); res.end('Hello, Middleware'); }); app.listen(3000); Thursday, January 3, 13
  10. Variable URLs var express = require("express"); var app = express();

    app.get('/', function (req, res) { res.send("Hello, World"); }); app.get('/greeting/:name/:location', function (req, res) { res.send("Hello, " + req.params.name + " from " + req.params.location); }); app.listen(3000); Thursday, January 3, 13
  11. Using Templates npm install hbs --save <div id="wrapper"> <header> <h2>{{title}}</h2>

    </header> <div class="content"> <p>Hello, {{name}}</p> </div> </div> var express = require('express'); var app = express(); app.configure(function () { app.set('view engine', 'hbs'); }); app.get('/', function (req, res) { res.render("index", { title: 'Important Title', name: 'Bob' }); }); app.use(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain' }); res.end('Hello, Middleware'); }); app.listen(3000); index.hbs app.js Thursday, January 3, 13
  12. Sharing Templates Between Frontend and Backend // register frontend partials,

    so they can be used on the backend var headerTmpl = fs.readFileSync(__dirname + '/public/templates/header.hbs', 'utf-8'); hbs.registerPartial('header', headerTmpl); <!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <title>Server Side Templates Example</title> <link rel="stylesheet" href="/stylesheets/ style.css"/> </head> <body> {{> header}} {{{body}}} </body> </html> Thursday, January 3, 13
  13. Other Middleware npm install less-middleware --save var express = require('express'),

    lessMiddleware = require('less-middleware'); var app = express(); app.configure(function () { app.set('view engine', 'hbs'); app.use(lessMiddleware({ src: __dirname + '/public' })); app.use(express.static(__dirname + '/public')); }); app.get('/', function (req, res) { res.render("index", { title: 'Important Title', name: 'Bob' }); }); app.get('/greeting/:name', function (req, res) { res.render("index", { name: req.params.name}); }); app.use(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain' }); res.end('Hello, Middleware'); }); app.listen(3000); Thursday, January 3, 13
  14. var fs = require("fs"), resolve = require("path").resolve; var fileData =

    [], interval = null, done = false, fileDir = resolve(__dirname, 'files'); fs.readdir(fileDir, function (err, files) { if (err) { console.log("error finding files: " + err); } else { files.forEach(function (file, index) { console.log("filename: " + file); fs.readFile(resolve(fileDir, file), "utf8", function (err, data) { if (err) { console.log("error reading file: " + err); } else { fileData.push(data); if (index === files.length - 1) { done = true; } } }); }); interval = setInterval(function () { if (done) { fs.writeFile(resolve(__dirname, 'out.txt'), fileData.join("\n"), "utf8", function (err) { if (err) { console.log('Error writing file: ' + err); } else { console.log('done'); } clearInterval(interval); }); } else { console.log('not done yet'); } }.bind(this), 10); } }); Thursday, January 3, 13
  15. var fs = require("fs"), comb = require("comb"), resolve = require("path").resolve;

    var fileData = [], interval = null, done = false, fileDir = resolve(__dirname, 'files'); var fsp = { readdir: comb.wrap(fs.readdir, fs), readFile: comb.wrap(fs.readFile, fs), writeFile: comb.wrap(fs.writeFile, fs) }; comb.async.forEach(fsp.readdir(fileDir), function (file, index) { var ret = new comb.Promise(); fsp.readFile(resolve(fileDir, file)).then(function (data) { fileData.push(data); ret.callback(); }); return ret.promise(); }).then(function () { fsp.writeFile(resolve(__dirname, 'out.promise.txt'), fileData.join("\n"), "utf8").then(function () { console.log('done'); }); }, function (err) { console.log("There was an error: " + err); }); Thursday, January 3, 13
  16. Promises • help manage callback hell • encourages separation of

    success and failure logic • error-bubbling Comb provides plenty of methods for helping manage callbacks, as well as a million other things! http://c2fo.github.com/comb/index.html Thursday, January 3, 13
  17. Example App: NebraskaJS Tweets • written using ntwitter and socket.io

    modules • First time using socket.io and connecting to twitter stream • follows #nebraskajs tagged tweets in real time • Try it now! tweet #nebraskajs • Source available at nicknisi/nebraskajs- tweets Thursday, January 3, 13