views:

161

answers:

2

Hey guys, im not well versed in dealing with asynchronous design patterns, and im having a problem writing a script that does two async data fetches.

Im using Dojo.data.api.Read.Fetch() to make two fetch() calls from seperate databases. The reulsts come back asynchronously. However, I have to cross reference the results, so i want my script to continue once BOTH async fetches are complete. I dont know how to do this, and therein lies the problem.

I am aware of the fetch's onComplete field and how to use it, BUT the best case solution i see there is to call the second fetch in the onComplete of the first fetch. I would like to do these fetches at the same time. Is there a way to do this?

Here's the current structure of my program for illustration purposes:

this.dict1.fetch({query:"blahblahblah", onComplete: function(items) { something here? }});
this.dict2.fetch({query:"blahblahbleh", onComplete: function(items) { or maybe something here? }});
this.orMaybeDoSomethingAfterBothFetches()

Any help would be greatly appreciated!

+1  A: 
// this is a variation of a function I have answered quite a few similar questions on SO with
function collected(count, fn){
    var loaded = 0;
    var collectedItems = [];
    return function(items){
        collectedItems = collectedItems.concat(items);
        if (++loaded === count){
             fn(collectedItems);
        } 
    }
}

var collectedFn = collected(2, function(items){
    //do stuff
});


this.dict1.fetch({query:"blahblahblah", onComplete: collectedFn);
this.dict2.fetch({query:"blahblahbleh", onComplete: collectedFn);

An alternative solution is

var store = {
    exec: function(){
        if (this.items1 && this.items2) {
            // do stuff with this.items1 and this.items2
        }
    }
};

this.dict1.fetch({query:"blahblahblah", onComplete: function(items) {
    store.items1 = items;
    store.exec();
});
this.dict2.fetch({query:"blahblahbleh", onComplete: function(items) {
    store.items2 = items;
    store.exec();
});
Sean Kinsey
I like, i like.
Dfowj
+1  A: 

You could create dojo.Deferreds for each of the fetches and then use dojo.DeferredList and add the deferreds to it - see here. This solution allows you to take advantage of adding 'n' functions to the list of functions you want to call. It also takes advantage of all the dojo.Deferred's callback and errBack functionality.

var fetch1 = new dojo.Deferred();
fetch1.addCallback(this.dict1.fetch...);
var fetch2 = new dojo.Deferred();
fetch2.addCallback(this.dict2.fetch...);

var allFuncs = new dojo.DeferredList([fetch1, fetch2]);
var doStuffWhenAllFuncsReturn = function() {...};
allFuncs.addCallback(doStuffWhenAllFuncsReturn);
Andy
One thing i don't understand about this is using the fetch's as the value to call the Deferred constructor on.. Isn't that the canceler? Care to explain how that works?
Dfowj
You are correct - see corrected code above.Looks like the API has changed in 1.5 so you might want to look at all the new promise based API and dojo.when.
Andy