Skip to content
Brian Cavalier edited this page Jan 9, 2012 · 8 revisions

A Deferred represents a computation or unit of work that may not have completed yet. Typically (but not always), that computation will be something that executes asynchronously and completes at some point in the future. For example, XHR operations (asynchronous ones, anyway, which it typical) in a browser never complete in the current turn of the Javascript event loop. Thus, an asynchronous XHR is one type of deferred computation.

A Deferred typically has a single producer (although having many produces can be useful, too) and many observers. A producer is responsible for providing the result of the computation, and typically, but not always, will be the same component that created the Deferred. As the name implies, an observer observes the result of the computation.

In when.js, producers provide a result via the Resolver API: deferred.resolve() or deferred.resolver.resolve(). The two are functionally equivalent, but deferred.resolver can safely be given out to an untrusted component without giving away full access to the Deferred. The resolver is also frozen and thus cannot be corrupted. That provides a clear separation of concerns by allowing a component to produce a result but not to know any details about observers.

Observers can observe the result via deferred.promise. The promise can be given to any number of components, who can observe the result using when(). They can also use .then(), but read why [[when()|when]] is usually a better choice. Like deferred.resolver, even though when.js's Deferred implements the Promise API, it is better to give only the deferred.promise to observers so that they can't modify the Deferred (such as calling resolve or reject on it!).

When a producer provides the result by calling deferred.resolver.resolve() (or deferred.resolve()), all observers are notified by having their callbacks (which they registered via when()) called with the result.

A producer may also reject the Deferred, signalling that the Deferred's computation failed, or could not complete given some set of constraints. In this case, all observers will be notified by having their errorback called (the 3rd parameter passed to when(), or the 2nd parameter passed to .then()).

when.js's Deferreds also support progress notifications, to indicate to observers that the computation is making progress toward its result. A producer may call deferred.resolver.progress() (or deferred.progress()) and pass a single parameter (whatever it wants) to indicate progress. All observers will be notified by having their progress handler called (the 4th parameter to when(), or the 3rd parameter to .then()).