"Apparently there is no built in method to wait on results. There were promisses but they were removed."

Because if you do that, the whole value proposition of Node.js completely falls apart. Now you've blocked the entire system waiting for your result. You might as well be programming in any other blocking language (all of which have Node.js-like libraries, by the way). This is what you get when you try to build concurrency on top of a language fundamentally built on non-concurrent primitives.

Consider going pure Erlang, which does work exactly the way you are looking for it to work. You call a function, which passes around messages and gets the result for you, and the result comes back along the function call, and all the not-blocking is handled by the Erlang VM, totally transparently. (Oh, and you get OTP, which if your server is non-trivial you really need, even if you don't know it yet. And transparent multi-proc support, easy clustering support, couple of other things that Node.js may someday have with great, great, great, great effort and even then they'll still be hacks unless they fundamentally change Javascript to basically become Erlang.)

Node.js is probably going to end up being a huge argument in favor of Erlang, because I suspect you will not be the last to encounter this problem in Node.js. It is absolutely inevitable that any significant application trying to be built in Node.js must collapse into a mess of callbacks and closures that will be very difficult to trace through. That's how it's designed. Any attempt to hack around this will have its own issues with gross hacks or difficulties with branching.

I really don't see Node.js being a success in the long term. It is built on a foundation that is not up to the task. Building a really big Node.js app would be a nightmare, and the reasons why are not going to come out of the foundation easily, if at all.

Here, let me give you an example with my work system I'm building. I have a single function which fans out an RPC request to multiple systems, collates the results with a timeout, and returns the results to the caller (or optionally calls some other code at the end, in the handler process). The initiator does not set up a callback, it just makes a call. The fanout mechanism does not set up a weird time-sliced mechanism to send out the calls, it just does it. There's some callbacks for handling whether it gets an error or a result coming back, which is pretty normal, and note, I don't have to contort around whether those callbacks may themselves want to do something over the network, they're just simple, one-layer callbacks that I would have implemented as callbacks in any language. (Imagine how you'd do that in an event-based system, deal with a response callback that may itself want to do a callback chain. It's perfectly feasible, I can easily see how to do it, but I sure as hell don't want to actually try to code it.) In Erlang, this is very natural; a function call that behind the scenes spawns a process that does what it says and says what it does, and works quite well. In an event-based system, this simple bit of functionality would be a callback explosion. I count a dozen, easily, and it would probably double if I really tried to do it. And that's not my whole system, either, it's just one bit. The multiplicative complexity explosion that occurs with Node.js's approach just isn't feasible.

(Note Erlang handles "events" quite well, indeed, it's a native paradigm for many parts of the system; what it doesn't have is the multiplicative explosion of manually-created event handlers caused by offloading the scheduling onto the programmer.)