cujojs/when — pull request #87 by Twisol (2013-01-12 11:01:34+00:00)
Title: Reduced nextTick usage

Hullo! This pull request is the result of a discussion on #cujojs about reducing the number of `nextTick` calls incurred by chaining calls to `then`. It isn't perfect, but it passes (all but two of) the unit tests. In developing this patch, I also ended up refactoring some parts of the code to make it easier to understand; this culminated in entirely unifying the code paths taken by resolve/reject and progress events.

The highlights:

1. `defer` now comes in two variants: an `asap` version that doesn't use nextTick, and a `defer` version that does. `asap` should only be used internally. This allows users to create new future computations that only incur a nextTick at the point of resolution, rather than between every promise in the chain.
2. Progress events use the same machinery as resolve and reject events. This unified the two event paths together, making the code a lot more understandable.
3. A new function, `shunt`, is used to defer continuation of a computation until the next tick. The difference between `defer` and `asap` boils down to this guy.

Open issues:
* Progress events are currently processed immediately, unlike the others. This seems in line with their intent, but should this be changed?
* It would be nice to unify `asap` and `defer` in some way, since the code is literally almost identical between them. This was just the quickest way to make it work.
* There's no way to wait on multiple promises without incurring a nextTick, as `asap` isn't exported. Rather than export `asap` directly, `some` and `map` should be updated to use `asap`. (Or better yet, fundamental synchronization primitives should be devised so that any multi-promise operation can be constructed. Maybe `some` and `map` fit the bill already; I just haven't looked into it.)