In terms of why this model is compelling: it scales well, and it's a relatively simple model of synchronization. The 5-line HTTP server on nodejs.org scales to a very large number of requests per second. Having spent a lot of time in the heavily multi-threaded C world (and loving it, btw), it's much harder to shoot yourself in the foot with JS and this model, and the failure modes are usually less severe. (Many C programs use this model as well, including haproxy and much of the kernel.)
It's not all win. Blocked operations are harder to debug. But you can work around things like that, and overall it's a nice environment. And FWIW, once you're familiar with it, the waterfall pattern quickly becomes as second-nature as writing synchronous code. (More complex ones are still tricky, but the basics do become second-nature.)
[edit: I meant that there's no sane possibility of a hybrid between synchronous and asynchronous semantics. That doesn't mean you couldn't use a language feature to make async code look synchronous. That's a much more subjective discussion, but I prefer explicitness over compiler magic.]