I have a few reasons why node-style callbacks are absolutely the worst possible choice, so I'd like to compare.
Here are some:
1. Not values. Values can participate in expressions, can be passed as arguments to functions, can be returned as values from functions, can be stored in variables, arrays, etc. There are no values with node-style callbacks. You are throwing away half of the language capabilities regarding values and expressions.
2. No guarantees. Callback may be called multiple times. It may be called synchronously or asynchronously. There is no way to know what will happen.
3. Bad semantics for thrown errors. Its assumed that thrown errors will simply crash the process. This is a dealbreaker in node because every uncaught thrown error provides a vector for denial of service attacks, and the thrown error semantics of most libraries and the standard node library are pretty bad.
I know most people use Promises to escape the call-back hell, but you can do that with async library as well, so maybe you just like writing "return cb(err);" more than "return Promise.reject(err);"
Maybe you like, that you need to deal with the err in the call-back, while \w promises it is easy to write code that just silently fails?
- They are simple (fully transparent)
- They are the simplest good enough solution for many problems
- Cleaner code than new Promise().then().then().then().catch() clutter
- Yes, I like nested indentations (good functions are short anyway)
- They perform well
As a side note, I also prefer coffeescript, snake_case, CONSTANTS, and avoid using classes, prototypes, and this. I'm not very happy with the recent development of EcmaScript, too much complexity and unnecessary new concepts.