dojo/promise at London Ajax User Group

dojo/promise at London Ajax User Group

Details on the new dojo/promise API in Dojo 1.8.


Mark Wubben

July 10, 2012


  1. What’s new in 1.8 dojo/promise A talk given at London

    Ajax User Group on July 10th, 2012.
  2. Brand new deferred/ Promise code Better tools for async programming

    Foundation for 2.0 Deprecated deferreds still around
  3. What’s old is new again This is for those of

    you who used Deferreds before.
  4. Deprecated, since 1.5… callback() & errback() addCallback/s(), addErrback(), addBoth() .fired,

  5. Deprecated, since 1.5… Mutation!

  6. But still available dojo.Deferred dojo/_base/Deferred Returned by older APIs

  7. Don’t use it!

  8. But note… dojo/_base/Deferred has then() and .promise, which return the

    new promise object
  9. Promises Are objects that are returned instead of the actual

    result Promise a result in the future Can be passed to other functions Of course promises are in jQuery as well, though they behave slightly differently.
  10. function doAsync(cb){ … cb(null, {}); } doAsync(function(error, result){ … });

    A typical example with Node-style callbacks.
  11. function doAsync(){ … return promise; } doAsync().then(function(result){ … }); Here

    doAsync returns a promise, and we hook up the callback later.
  12. var promise = doAsync(); useAsyncResult(promise); But because the promise encapsulates

    the async operation, we can pass it to another function as well. You can’t do this with callbacks.
  13. dojo/Deferred Provides the Deferred base class Let's explain through the

    new API.
  14. require([ "dojo/Deferred" ], function(Deferred){ var deferred = new Deferred(); …

    }); We can require the constructor into our code.
  15. function doAsync(){ var deferred = new Deferred(); … return deferred.promise;

    } So let's say we have a function that is asynchronous and should return a promise. Construct the deferred at the top of the function, and return the promise at the end.
  16. // Resolve a deferred if the async operation // completed

    successfully. deferred.resolve(result);
  17. // Reject a deferred if the async operation // failed.

  18. // Add a callback deferred.then(function(result){ … }); deferred.promise.then(function(result){ … });

    We can then add callbacks to the returned promise.
  19. // Add an errback deferred.then(null, function(error){ … }); deferred.promise.then(null, function(error){

    … }); Or errbacks.
  20. dojo/promise/Promise Used as the return value Can't be resolved itself,

    that's the deferred Chaining!
  21. // Construct a promise chain promise.then(function(result){ … }).then(function(result){ … });

    then() itself also returns a promise, to which we can add another callback.
  22. // Return a promise from the callback promise.then(function(){ return doAsync();

  23. // Add callbacks before deferred is resolved deferred.promise.then(function(){ … });

  24. // … or after deferred.resolve(result); deferred.promise.then(function(){ … });

  25. // Results & errors bubble even if no // callbacks

    are registered promise.then(function(){ … }).then(null, function(error){ … }); deferred.reject(error);
  26. // Thrown errors are handled by the resulting // promise

    promise.then(function(){ throw new Error(); }, function(error){ // Not called! });
  27. Values must be returned, errors (re)thrown

  28. Message channels Success: resolve(), callbacks Failure: reject(), errbacks

  29. More message channels Progress: progress(), progbacks Cancelation: cancel(), canceler

  30. // Report progress on the deferred deferred.progress("50% done!");

  31. // Add a progback promise.then(null, null, function(update){ … );

  32. Progress updates are not cached by the promise. Progbacks must

    be registered or updates will be missed
  33. // Create a deferred with a canceler var deferred =

    new Deferred(function(reason){ … });
  34. // Cancel a deferred deferred.cancel(); deferred.promise.cancel();

  35. // Canceling works with chaining promise.then().then().then().cancel();

  36. // Tell the deferred why it's being canceled promise.cancel(new OperationAbortedError());

  37. Sugar

  38. // Determine state of the deferred deferred.isResolved(); deferred.isRejected(); deferred.isCanceled(); deferred.isFulfilled();

  39. // Determine state of the promise promise.isResolved(); promise.isRejected(); promise.isCanceled(); promise.isFulfilled();

  40. // Easier callbacks promise.always(function(resultOrError){ … }); promise.otherwise(function(error){ … });

  41. Resolving twice is ignored, usually

  42. // With a fulfilled deferred, resolving // is normally ignored:

    deferred.resolve("again!"); // Unless strict mode is desired: deferred.resolve("again!", true); Same for reject(), progress() and cancel(). With the old Deferred this throws an error.
  43. dojo/when Newer version of dojo.when Require separately

  44. // When you don't know if you have a promise

    when(promiseOrValue, function(value){ … });
  45. // Used without direct callback, converts // into a dojo/promise/Promise

    when(promiseOrValue).then(function(result){ … });
  46. // With direct callback, will call right away // if

    passed a value, without catching errors // thrown by callback. Does not return a // promise. when(value, function(value){ throw new Error(); }); // Throws!
  47. dojo/promise/first dojo/promise/all Replaces dojo.DeferredList

  48. // Returns promise fulfilled when the first // promise is

    resolved or rejected. Resolves // returned promise with result of first. first([promise1, promise2]) first({ p1: promise1, p2: promise2 })
  49. // Returns promise fulfilled when all // promises are resolved

    or one is rejected. // Resolves returned promise with list or // object of results. all([promise1, promise2]) all({ p1: promise1, p2: promise2 })
  50. cancel() doesn't cancel the promises passed to first() or all(),

    only the returned promise
  51. Error instrumenting Automatically log unhandled errors during development Pluggable interface

  52. Tracing Trace results, errors and progress updates Again automatic during

  53. promise.trace(); deferred.resolve("hello?"); // Logs "resolved", "hello?"

  54. I’m @novemberborn or Cheers! And that’s all folks. Further