That's actually quite a painful way to write async code because the control flow is now inside the functions. That makes it very hard to perform refactoring.
Might I suggest you take a look at my preferred solution for this,
I've actually been put off Node a little because I've not seen any examples using this style of code. I had (perhaps stupidly) assumed that the scope of a closure was necessary for a lot of Node functionality; generally speaking, are all the parameters required for interacting with Node passed via the function parameters?
Well, beyond a style issue. You can unfold the events and make it a lot less "annoying".
Consider,
var cb1 = function() {
}
var cb2 = function() {
}var cb3 = function() {
}req(cb3);
It's a lot cleaner and it looks like a state machine (and kind of looks like erlang/message passing).