Your SlideShare is downloading. ×

Node.js - Best practices

50,419

Published on

Second talk given at the munich node.js user group meeting on Dec 1, 2011.

Second talk given at the munich node.js user group meeting on Dec 1, 2011.

Published in: Technology
2 Comments
197 Likes
Statistics
Notes
No Downloads
Views
Total Views
50,419
On Slideshare
0
From Embeds
0
Number of Embeds
17
Actions
Shares
0
Downloads
1,009
Comments
2
Likes
197
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • \n
  • \n
  • \n
  • If you’re function works like this, I will not use it\n
  • Otherwise JSON.parse(undefined) -> SyntaxError: Unexpected token ILLEGAL \n
  • Otherwise invalid JSON -> SyntaxError: Unexpected token ILLEGAL\n
  • Otherwise I always have to -> if (json instanceof Error) ...\n
  • Subtle: Do not catch errors inside your callback -> very unexpected results\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Fake photograph btw.: http://www.snopes.com/photos/politics/bushbook.asp\n
  • Nested callbacks are an actual concern in the node community\n
  • \n
  • \n
  • \n
  • \n
  • Please DO NOT EVER use exceptions for control flow.\n\nLike so many things in JS, JSON.parse() throwing exceptions is bullshit.\n
  • \n
  • \n
  • \n
  • Also known as Stage 3 / Bargaining stage in Kübler-Ross model of “The Five Stages of Grief”\n
  • \n
  • If rows.length === 0 the exception triggered from accessing rows[0].id will STALL your database driver. Not good!\n
  • \n
  • Higher level could be upstart / monit / etc.\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript

    • 1. Best PracticesFelix Geisendörfer Munich Node.js User Group 01.12.2011 (v1)
    • 2. (@)felixge(.de)Twitter / GitHub / IRC Felix Geisendörfer (Berlin, Germany)
    • 3. Callbacks
    • 4. A terrible Example:var fs = require(fs);function readJSON(path, cb) { fs.readFile(path, utf8, function(err, data) { cb(JSON.parse(data)); });}
    • 5. Error Delegationvar fs = require(fs);function readJSON(path, cb) { fs.readFile(path, utf8, function(err, data) { if (err) return cb(err); cb(JSON.parse(data)); });}
    • 6. Exception Handlingvar fs = require(fs);function readJSON(path, cb) { fs.readFile(path, utf8, function(err, data) { if (err) return cb(err); try { cb(JSON.parse(data)); } catch (err) { cb(err); } });}
    • 7. Error parameter firstvar fs = require(fs);function readJSON(path, cb) { fs.readFile(path, utf8, function(err, data) { if (err) return cb(err); try { cb(null, JSON.parse(data)); } catch (err) { cb(err); } });}
    • 8. Not your errorvar fs = require(fs);function readJSON(path, cb) { fs.readFile(path, utf8, function(err, data) { if (err) return cb(err); try { var json = JSON.parse(data); } catch (err) { return cb(err); } cb(null, json); });}
    • 9. Another common mistakefunction readJSONFiles(files, cb) { var results = {}; var remaining = files.length; files.forEach(function(file) { readJSON(file, function(err, json) { if (err) return cb(err); results[file] = json; if (!--remaining) cb(null, results); }); });}
    • 10. Only call back oncefunction readJSONFiles(files, cb) { var results = {}; var remaining = files.length; files.forEach(function(file) { readJSON(file, function(err, json) { if (err) { cb(err); cb = function() {}; return; } results[file] = json; if (!--remaining) cb(null, results); }); });}
    • 11. Nested Callbacks
    • 12. db.query(SELECT A ..., function() { db.query(SELECT B ..., function() { db.query(SELECT C ..., function() { db.query(SELECT D ..., function() { db.query(SELECT E ..., function() { db.query(SELECT F ..., function() { db.query(SELECT G ..., function() { db.query(SELECT H ..., function() { db.query(SELECT I ..., function() { }); }); }); }); }); }); }); });});
    • 13. iPhone 4 owners?
    • 14. You are holding it wrong!
    • 15. Just kidding
    • 16. Control Flow Libs var async = require(async); async.series({ queryA: function(next) { db.query(SELECT A ..., next); }, queryB: function(next) { db.query(SELECT A ..., next); }, queryC: function(next) { db.query(SELECT A ..., next); } // ... }, function(err, results) { });
    • 17. Split code into more methods
    • 18. Maybe node.js is not a good tool for your problem?
    • 19. Exceptions(Dealing with Death)
    • 20. Exceptionsthrow new Error(oh no); Explicit, useful to crash your program
    • 21. Exceptionsnode.js:134 throw e; // process.nextTick error, or error event on first tick ^Error: oh no at Object.<anonymous> (/Users/felix/explicit.js:1:69) at Module._compile (module.js:411:26) at Object..js (module.js:417:10) at Module.load (module.js:343:31) at Function._load (module.js:302:12) at Array.<anonymous> (module.js:430:10) at EventEmitter._tickCallback (node.js:126:26) Output on stderr
    • 22. Exceptionsfunction MyClass() {}MyClass.prototype.myMethod = function() { setTimeout(function() { this.myOtherMethod(); }, 10);};MyClass.prototype.myOtherMethod = function() {};(new MyClass).myMethod(); Implicit, usually undesirable / bugs
    • 23. Exceptions/Users/felix/implicit.js:5 this.myOtherMethod(); ^TypeError: Object #<Object> has no method myOtherMethod at Object._onTimeout (/Users/felix/implicit.js:5:10) at Timer.callback (timers.js:83:39) Incomplete stack trace : (
    • 24. Global Catchprocess.on(uncaughtException, function(err) { console.error(uncaught exception: + err.stack);});
    • 25. Please be careful with this!
    • 26. Global catch gone wrong// Deep inside the database driver you are usingcb(null, rows);this._executeNextQueuedQuery();// In your codedb.query(SELECT ..., function(err, rows) { console.log(First row: + row[0].id);});
    • 27. If you have to:process.on(uncaughtException, function(err) { // You could use node-airbake for this sendErrorToLog(function() { // Once the error was logged, kill the process console.error(err.stack); process.exit(1); });});
    • 28. Even Better Processes die. Accept it.Deal with it on a higher level.
    • 29. Deployment
    • 30. Novice$ node server.js
    • 31. Advanced Beginner $ node server.js &
    • 32. Competent$ screen$ node server.js
    • 33. Proficient#!/bin/bashwhile :do node server.js echo "Server crashed!" sleep 1done
    • 34. Expert#!upstartdescription "myapp"author "felix"start on (local-filesystems and net-device-upIFACE=eth0)stop on shutdownrespawn # restart when job diesrespawn limit 5 60 # give up restart after 5respawns in 60 secondsscript exec sudo -u www-data /path/to/server.js >> /var/log/myapp.log 2>&1end script
    • 35. Innovation$ git push joyent master$ git push nodejitsu master$ git push heroku master
    • 36. Questions? @felixge
    • 37. Thank you!

    ×