Slide 1

Slide 1 text

What’s new in 1.8 dojo/promise A talk given at London Ajax User Group on July 10th, 2012.

Slide 2

Slide 2 text

Brand new deferred/ Promise code Better tools for async programming Foundation for 2.0 Deprecated deferreds still around

Slide 3

Slide 3 text

What’s old is new again This is for those of you who used Deferreds before.

Slide 4

Slide 4 text

Deprecated, since 1.5… callback() & errback() addCallback/s(), addErrback(), addBoth() .fired, .results

Slide 5

Slide 5 text

Deprecated, since 1.5… Mutation!

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

Don’t use it!

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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.

Slide 10

Slide 10 text

function doAsync(cb){ … cb(null, {}); } doAsync(function(error, result){ … }); A typical example with Node-style callbacks.

Slide 11

Slide 11 text

function doAsync(){ … return promise; } doAsync().then(function(result){ … }); Here doAsync returns a promise, and we hook up the callback later.

Slide 12

Slide 12 text

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.

Slide 13

Slide 13 text

dojo/Deferred Provides the Deferred base class Let's explain through the new API.

Slide 14

Slide 14 text

require([ "dojo/Deferred" ], function(Deferred){ var deferred = new Deferred(); … }); We can require the constructor into our code.

Slide 15

Slide 15 text

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.

Slide 16

Slide 16 text

// Resolve a deferred if the async operation // completed successfully. deferred.resolve(result);

Slide 17

Slide 17 text

// Reject a deferred if the async operation // failed. deferred.reject(error);

Slide 18

Slide 18 text

// Add a callback deferred.then(function(result){ … }); deferred.promise.then(function(result){ … }); We can then add callbacks to the returned promise.

Slide 19

Slide 19 text

// Add an errback deferred.then(null, function(error){ … }); deferred.promise.then(null, function(error){ … }); Or errbacks.

Slide 20

Slide 20 text

dojo/promise/Promise Used as the return value Can't be resolved itself, that's the deferred Chaining!

Slide 21

Slide 21 text

// Construct a promise chain promise.then(function(result){ … }).then(function(result){ … }); then() itself also returns a promise, to which we can add another callback.

Slide 22

Slide 22 text

// Return a promise from the callback promise.then(function(){ return doAsync(); });

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

// Results & errors bubble even if no // callbacks are registered promise.then(function(){ … }).then(null, function(error){ … }); deferred.reject(error);

Slide 26

Slide 26 text

// Thrown errors are handled by the resulting // promise promise.then(function(){ throw new Error(); }, function(error){ // Not called! });

Slide 27

Slide 27 text

Values must be returned, errors (re)thrown

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

Progress updates are not cached by the promise. Progbacks must be registered or updates will be missed

Slide 33

Slide 33 text

// Create a deferred with a canceler var deferred = new Deferred(function(reason){ … });

Slide 34

Slide 34 text

// Cancel a deferred deferred.cancel(); deferred.promise.cancel();

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

Sugar

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

Resolving twice is ignored, usually

Slide 42

Slide 42 text

// 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.

Slide 43

Slide 43 text

dojo/when Newer version of dojo.when Require separately

Slide 44

Slide 44 text

// When you don't know if you have a promise when(promiseOrValue, function(value){ … });

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

// 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!

Slide 47

Slide 47 text

dojo/promise/first dojo/promise/all Replaces dojo.DeferredList

Slide 48

Slide 48 text

// 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 })

Slide 49

Slide 49 text

// 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 })

Slide 50

Slide 50 text

cancel() doesn't cancel the promises passed to first() or all(), only the returned promise

Slide 51

Slide 51 text

Error instrumenting Automatically log unhandled errors during development Pluggable interface dojo/promise/instrumenting

Slide 52

Slide 52 text

Tracing Trace results, errors and progress updates Again automatic during development

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

I’m @novemberborn or [email protected] Cheers! And that’s all folks. Further questions?