Slide 1

Slide 1 text

Node.js Brandon Cannaday Aug. 8th, 2012 http://modulus.io Intro and Callbacks Thursday, August 9, 12

Slide 2

Slide 2 text

HISTORY • Invented in 2009 by Ryan Dahl • Created to address non- currency issues in most server-side frameworks • Currently owned and maintained by Joyent http://www.youtube.com/watch?v=SAc0vQCC6UQ Thursday, August 9, 12

Slide 3

Slide 3 text

WHAT IS IT? • Server-side scripting framework • Like Rails and PHP except for JavaScript • Google’s V8 Engine • Single threaded, non- blocking Thursday, August 9, 12

Slide 4

Slide 4 text

USE CASES • Good at: • Data-driven APIs • Real-time apps • Websites • Scaling • Bad at: • Data crunching Thursday, August 9, 12

Slide 5

Slide 5 text

fs.readFile(‘myFile.txt’, readComplete) The ‘real’ work Function to call when it’s done (the callback) NON-BLOCKING All ‘real’ work is done async Thursday, August 9, 12

Slide 6

Slide 6 text

CALLBACK HELL Thursday, August 9, 12

Slide 7

Slide 7 text

var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; }); app.listen(80); Get posted user CALLBACK HELL User Registration Example Thursday, August 9, 12

Slide 8

Slide 8 text

var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; bcrypt.genSalt(function(err, salt) { if(err === null) { } else { // Failed to generate salt res.send(err); } }); }); app.listen(80); Generate hash salt Get posted user CALLBACK HELL User Registration Example Thursday, August 9, 12

Slide 9

Slide 9 text

var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; bcrypt.genSalt(function(err, salt) { if(err === null) { bcrypt.hash(user.pwd, salt, function(err, hash) { if(err === null) { } else { // Failed to generate hash res.send(err); } }); } else { // Failed to generate salt res.send(err); } }); }); app.listen(80); Generate hash salt Get posted user Generate hash CALLBACK HELL User Registration Example Thursday, August 9, 12

Slide 10

Slide 10 text

var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; bcrypt.genSalt(function(err, salt) { if(err === null) { bcrypt.hash(user.pwd, salt, function(err, hash) { if(err === null) { user.passHash = hash; db.saveUser(user, function(err, result) { if(err === null) { res.send('SUCCESS!'); } else { // Failed to save user res.send(err); } }); } else { // Failed to generate hash res.send(err); } }); } else { // Failed to generate salt res.send(err); } }); }); app.listen(80); Generate hash salt Get posted user Save user to the DB Generate hash CALLBACK HELL User Registration Example Thursday, August 9, 12

Slide 11

Slide 11 text

Translate a nested flow into a linear flow https://github.com/caolan/async/ Async.js Thursday, August 9, 12

Slide 12

Slide 12 text

Async.js var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; bcrypt.genSalt(function(err, salt) { if(err === null) { bcrypt.hash(user.pwd, salt, function(err, hash) { if(err === null) { user.passHash = hash; db.saveUser(user, function(err, result) { if(err === null) { res.send('SUCCESS!'); } else { // Failed to save user res.send(err); } }); } else { // Failed to generate hash res.send(err); } }); } else { // Failed to generate salt res.send(err); } }); }); app.listen(80); var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), async = require('async'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; async.waterfall([ // Functions to execute ], function(err, result) { // Called on any error or at end }); app.listen(80); Thursday, August 9, 12

Slide 13

Slide 13 text

var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; bcrypt.genSalt(function(err, salt) { if(err === null) { bcrypt.hash(user.pwd, salt, function(err, hash) { if(err === null) { user.passHash = hash; db.saveUser(user, function(err, result) { if(err === null) { res.send('SUCCESS!'); } else { // Failed to save user res.send(err); } }); } else { // Failed to generate hash res.send(err); } }); } else { // Failed to generate salt res.send(err); } }); }); app.listen(80); var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), async = require('async'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; async.waterfall([ function(callback) { bcrypt.genSalt(callback); } ], function(err, result) { // Called on any error or at end }); app.listen(80); Async.js Thursday, August 9, 12

Slide 14

Slide 14 text

var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; bcrypt.genSalt(function(err, salt) { if(err === null) { bcrypt.hash(user.pwd, salt, function(err, hash) { if(err === null) { user.passHash = hash; db.saveUser(user, function(err, result) { if(err === null) { res.send('SUCCESS!'); } else { // Failed to save user res.send(err); } }); } else { // Failed to generate hash res.send(err); } }); } else { // Failed to generate salt res.send(err); } }); }); app.listen(80); var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), async = require('async'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; async.waterfall([ function(callback) { bcrypt.genSalt(callback); }, function(salt, callback) { bcrypt.hash(user.password, salt, callback); } ], function(err, result) { // Called on any error or at end }); app.listen(80); Async.js Thursday, August 9, 12

Slide 15

Slide 15 text

var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; bcrypt.genSalt(function(err, salt) { if(err === null) { bcrypt.hash(user.pwd, salt, function(err, hash) { if(err === null) { user.passHash = hash; db.saveUser(user, function(err, result) { if(err === null) { res.send('SUCCESS!'); } else { // Failed to save user res.send(err); } }); } else { // Failed to generate hash res.send(err); } }); } else { // Failed to generate salt res.send(err); } }); }); app.listen(80); var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), async = require('async'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; async.waterfall([ function(callback) { bcrypt.genSalt(callback); }, function(salt, callback) { bcrypt.hash(user.password, salt, callback); }, function(hash, callback) { user.passHash = hash; db.saveUser(user, callback); } ], function(err, result) { // Called on any error or at end }); app.listen(80); Async.js Thursday, August 9, 12

Slide 16

Slide 16 text

var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; bcrypt.genSalt(function(err, salt) { if(err === null) { bcrypt.hash(user.pwd, salt, function(err, hash) { if(err === null) { user.passHash = hash; db.saveUser(user, function(err, result) { if(err === null) { res.send('SUCCESS!'); } else { // Failed to save user res.send(err); } }); } else { // Failed to generate hash res.send(err); } }); } else { // Failed to generate salt res.send(err); } }); }); app.listen(80); var express = require('express'), bcrypt = require('bcrypt'), db = require('database'), async = require('async'), app = express(); app.post('/user/register', function(req, res) { var user = req.body.user; async.waterfall([ function(callback) { bcrypt.genSalt(callback); }, function(salt, callback) { bcrypt.hash(user.password, salt, callback); }, function(hash, callback) { user.passHash = hash; db.saveUser(user, callback); } ], function(err, result) { if(err === null) { res.send('SUCCESS!'); } else { res.send(err); } }); app.listen(80); Async.js Thursday, August 9, 12

Slide 17

Slide 17 text

https://github.com/joyent/node/wiki/modules#wiki-async-flow CALLBACK PURGATORY Thursday, August 9, 12

Slide 18

Slide 18 text

• STEP 1: npm install express • STEP 2: npm install async SUMMARY Thursday, August 9, 12

Slide 19

Slide 19 text

Thanks! @TheReddest Thursday, August 9, 12