Returning a Deferred object within a Deferred Callback does The Right Thing

6 Feb

dojo.Deferred is very cool, but it’s very easy to tie yourself up in knots. It’s worth spending some time reading about it. The official API doc is good, as is this article which discuss what’s new in Dojo 1.5 on the topic of Deferreds.

One thing in particular that isn’t always obvious is that a callback function itself can return a Deferred. In this case, Dojo will do the right thing, and insert this into the callback chain in the right place. This can make your code much simpler and avoid nasty hacks with co-dependent Deferreds. To illustrate, let’s start off with a simple example that doesn’t exploit that feature:

function sayHello() {
    var deferred = new dojo.Deferred();
    var name = "Fred";
    console.debug("Hello", name);
    deferred.callback(name);
    return deferred;
}

sayHello().then(function(name) {
    console.debug("Goodbye", name);
});

This should print “Hello Fred”, then “Goodbye Fred” in your debugger. Note that we are firing the callback explicitly above. In reality, this is far more likely to be based on the result of an asynchronous call – typically an XHR request. Treat the sayHello() method as a black-box for the purposes of this illustration – the important point is that it returns a Deferred (and that aspect of the function signature can’t be changed).

Now let’s imagine that you need to insert sayHello() into the middle of a Deferred chain. Let’s remove the final three lines from the code above, and add this additional code:

function prepareForArrival() {
    var deferred = new dojo.Deferred();
    console.debug("Preparing for the arrival of an unknown guest");
    deferred.callback();
    return deferred;
}

prepareForArrival().then(sayHello).then(function (name) {
    console.debug("Goodbye", name);
});

You should now see: “Preparing for the arrival of an unknown guest”, then “Hello Fred”, then “Goodbye Fred”.

This works because the then() method takes a callback function as its first argument. Often, you will specify a function which returns a regular value to be passed along to the next callback (i.e. the next then() method) in the chain. However, in this case, we have specified a function which returns a Deferred. Dojo realises this, and inserts that Deferred into the call chain instead. It is executed next, and the result of the callback method from that Deferred is passed into the “goodbye function”.

Remembering this trick can greatly simplify the readability and structure of your code, and allow you to construct complex Deferred chains in a straightforward manner.

About these ads

One Response to “Returning a Deferred object within a Deferred Callback does The Right Thing”

  1. xxjthxx 2012/07/02 at 19:56 #

    That’s a REALLY nice and smart feature INDEED. You can add some dependencies between Deferred like one Deffered cannot start until the other get the result… Brilliant!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 82 other followers

%d bloggers like this: