Both interfaces can be abused to give you an ever growing indent and give the appearance of "callback hell"
Both interfaces can be use elegantly to help you reason about your code, make it easy to follow, and handle errors centrally.
Only one is supported natively by node.js and is the standard async interface for 90% of node.js's libraries: Callbacks.
Also, regarding "callback hell", a straw-man argument against callbacks, I highly suggest reading http://callbackhell.com/
By utilizing callbacks, you are free to use Async.js[0] or Step.js[1] to solve the problem you described. These libraries are great since they give you control over parallel vs series execution of the pre-requisite functions as well as solving more complex control-flow problems such as throttling, etc[2] (See link for more examples).
[0] https://github.com/caolan/async
[1] https://github.com/creationix/step
[2] https://github.com/caolan/async#control-flow
edit: Yes, you can also use similar control-flow libraries with Promises (that follow the specification) to achieve similar results but then the argument for using promises for the sake of control-flow breaks down.
- sequential execution
- parallel execution and wait for all of them to finish
- automated error handling