Tag Archives: async

Using Dojo Partial to mixin variables

16 Feb

Came across the same problem a few times now where I’ve wanted to get at my variables inside a dojo.hitch statement. This problem seems to crop up when performing an async request and then doing ‘something’ with it’s response. In the case below, our useful values are ‘undefined’ inside the hitch:

var attr = "badger";
var value = "apple";

//this is the result of an async datastore query
var gotItem = dojo.hitch(this, function(item) {
    //update item
   this.updateItem(item, attr, value); // <--- This will FAIL
});

The solution I have used before, is to mixin my values into the hitch scope, ie.

var scope = {"attr":attr, "val":val, "parent":this}
dojo.hitch(scope, function(){
    var val = this.val // <-- this works, but it's a bit nasty!
    //etc... etc...
})

However, using dojo partial mixes in the extra values as the first params to the hitch, with the item (from out previous example) being the final attr.

var attr = "badger";
var value = "apple";

//this is the result of an async datastore query
var gotItem = dojo.partial(dojo.hitch(this, function(attr, value, item) {
    //update item
   this.updateItem(item, attr, value); // <-- This will WORK!!
}), attr, value ); // <-- these values will be mixed in

So go on, try it!!

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.

Follow

Get every new post delivered to your Inbox.

Join 81 other followers