That's some serious callback hell. See any problems? For one, the user input won't be captured until both AJAX calls (cats, dogs) are completed, and they are not done in parallel, either. Further, the AJAX calls triggered by user input do not necessarily return in the same order as they are issued, so the last call to "doStuff" might be based on stale data. That might prove hard to fix?

You're absolutely right regarding Promises. Promises indeed provide a very similar interface to Bacon.js streams and allow you to compose data from asynchronous sources in a nice way.

What I didn't know was that you can use $.when() to compose parallel promises like that.

The main difference between Promises and EventStreams is that the latter may contain multiple values over time. For many applications (including AJAX), they provide roughly equivalent power of expression.