The callback hell that never was

Let's talk about callbacks. People seem to get terrified by them, because they see something like this:
var mysql = require('mysql'),
db = mysql.createClient({
user: 'root',
password: 'root'
}),
id = 1;
db.query('USE mydb', function (err) {
//some code here
db.query('SELECT * FROM whatever WHERE id=?', [id], function (err, foo) {
if (foo) {
//some other code
db.query('UPDATE whatever SET bar=?', [foo.bar], function (err) {
db.query('INSERT INTO someothertable (sometime) VALUES (NOW())', function () {
//some code
console.log("It's done");
});
});
}
});
//more code
});This has the potential to turn into hard to understand spaghetti code. But we don't have to write it like this. We don't have to inline every function; we can simply name them instead.
var mysql = require('mysql'),
db = mysql.createClient({
user: 'root',
password: 'root'
}),
id = 1;
function init(fn) {
db.query('USE mydb', fn);
}
function fetch(id, fn) {
db.query('SELECT * FROM whatever WHERE id=?', [id], fn);
}
function checker(err, foo) {
if (foo) {
//some other code
update(foo.bar);
}
}
function update(bar) {
db.query('UPDATE whatever SET bar=?', [bar], function (err) {
db.query('INSERT INTO someothertable (sometime) VALUES (NOW())', function () {
//some code
console.log("It's done");
});
});
}
init(function () {
fetch(id, checker);
})We could also put this in a module or wrap a (pseudo) class around it if we wanted to. The main point is that we don't have to nest inline callbacks to get the job done; we can name them.