Skip to content
Eugene Lazutkin edited this page Mar 16, 2016 · 3 revisions

FastDeferred is modelled after async.Deferred. It supports the same exact API, and shares the same semantic behavior. But it has two important differences:

  1. It doesn't mess with exceptions, it doesn't catch them, and it doesn't convert them automatically to rejected promises. That decision makes them faster, and easier to debug.
  2. It doesn't support the shortcut provided by Deferred: if an undefined is returned, it means that the previous value should be passed or thrown. Just like with standard Promise, user should always return explicitly the value to be passed to the next callback. If undefined is returned, it will be passed through.

To demonstrate the difference, let's construct simple pass-through callbacks for a standard promise (or a promise produced by Deferred):

// promise is produced by Deferred or Promise
promise.then(
  function (value) { return value; },  // callback
  function (error) { throw error; }    // errback
);

Note that the "errback" above relies on an exception being converted to a rejected promise. Essentially we are throwing errors on purpose to facilitate this behavior. If we want to continue our processing down the error path, we have to rethrow all errors over and over again. A throw is an expensive operation.

FastDeferred uses a different pattern to achieve the same results:

// promise is produced by Deferred or Promise
promise.then(
  function (value) { return value; },                      // callback
  function (error) { return FastDeferred.reject(error); }  // errback
);

It avoids throwing anything, just returns an explicitly rejected promise.

Does it mean that a user should use different patterns when switching promise implementations? No. The pattern above used by FastDeferred is a universal pattern. It works on all implementations of promises:

var P = Promise; // or
// var P = Deferred.Wrapper; // or
// var P = FastDeferred.Wrapper;
// ...
promise.catch(
  function (error) { return P.reject(error); }
);

So it makes it possible to start using FastDeferred for development and debugging, then switch to Deferred or Promise, providing that explicit rejections are used to indicate errors consistently throughout the code.