function myApp(data, cb) {
doSomethingAsync(data, function (err, result) {
computeResult(result, function (err, result) {
cb(null, result)
})
})
}
Can you spot the mistake?
function myApp(data, cb) {
doSomethingAsync(data, function (err, result) {
if (err) return cb(err)
computeResult(result, function (err, result) {
if (err) return cb(err)
cb(null, result)
})
})
}
function createIfNotExist(file, content, cb) {
fs.stat(file, function (err, stat) {
// if err is a no such file then create it
if (err.code === "ENOENT") {
fs.writeFile(file, content, cb)
} else if (err) {
cb(err)
} else {
cb(null, null)
}
})
}
function handleRequest(req, res) {
parseJSONBody(req, res, function (err, body) {
if (err) return DO_SOMETHING
model.fetchStuff(body.id, function (err, record) {
if (err) return DO_SOMETHING
res.end(JSON.stringify(record))
})
})
}
function handleRequest(req, res) {
parseJSONBody(req, res, function (err, body) {
if (err) return res.end(err.message)
model.fetchStuff(body.id, function (err, record) {
if (err) return res.end(err.message)
res.end(JSON.stringify(record))
})
})
}
Can you spot the problem?
function handleRequest(req, res, opts, cb) {
parseJSONBody(req, res, function (err, body) {
if (err) return cb(err)
model.fetchStuff(body.id, function (err, record) {
if (err) return cb(err)
res.end(JSON.stringify(record))
})
})
}
var logger = bunyan.createLogger({ ... })
// in router.js
function logError(req, res, err) {
logger.error({
methodName: value.name,
error: extend(value.err, {
stack: value.err.stack,
name: value.err.name
}),
id: err.id,
args: value.args,
req: req,
res: res,
user: req.user
})
}
// server.js
function handleRequest(req, res) {
model.fetch(function (err, data) {
if (err) return sendJson(req, res, {
message: err.message
})
sendJson(req, res, { data: data })
})
}
// browser.js
request({ ... }, function (err, res, body) {
if (body.message) {
if (/Invalid email/.test(body.message)) {
validationElem.textContent = "Invalid email"
}
}
})
// server.js
function handleRequest(req, res) {
model.fetch(function (err, data) {
if (err) return sendJson(req, res, {
message: err.message,
type: "invalid.email",
attribute: "email"
})
})
}
// browser.js
request({ ... }, function (err, res, body) {
if (body.type && body.type.substr(0, 7) === "invalid") {
validationElems[body.attribute].textContent =
"Invalid " + body.attribute
}
})
module.exports = function fetch(name, cb) {
db.cache.get(name, function (err, value) {
if (err) {
logger({ name: "cache.get", args: [name], err: err })
return cb(err)
}
cb(null, value)
})
}
function logged(obj, logger) {
Object.keys(obj).forEach(function (key) { var fn = obj[key];
obj[key] = function () {
var args = slice.call(arguments), cb = args.pop()
return fn.apply(this, args.concat([function (err) {
if (err) logger({
name: key, args: args, err: err
})
cb.apply(this, arguments)
}]))
}
})
}
function handleRequest(req, res, opts, cb) {
getSession(req, res, function (err, user) {
if (err) return cb(err)
fetchRecords(user.email, function (err, records) {
if (err) return cb(err)
sendJson(req, res, records)
})
})
}
Can you spot the mistake?
function handleRequest(req, res, opts, cb) {
getSession(req, res, function (err, user) {
if (err) return cb(err)
// TypeError: Cannot read property 'email' of null
fetchRecords(user.email, function (err, records) {
if (err) return cb(err)
sendJson(req, res, records)
})
})
}
Classic null property access errors
domains allow you to handle thrown exceptions.
Think of them as uncaughtException but per req/res
var domain = require("domain")
function handleRequest(req, res) {
var fn = matchRoute(req, res, router)
var d = domain.create()
d.add(req)
d.add(res)
d.on("error", handleError)
d.run(function () {
fn(req, res, {}, handleError)
})
function handleError() { ... }
}
Sometimes your process goes down and there are no errors
Thankfully you will have a core dump
If you are on joyent just open mdb on the core dump and have a look