pvitt
pvitt

Reputation: 1065

return object store value by calling dojo module

I was hoping to get a value (an object store) calling my dojo module, but I keep getting undefined :

module:

define(['dojo/store/Memory', 'dojo/_base/xhr', "dojo/data/ObjectStore"],
        function (Memory, xhr, ObjectStore) {
    var oReachStore;
    return {
        Reaches: function (url) {
            xhr.get({//get data from database
                url: url,
                //url: url,
                handleAs: "json",
                load: function (result) {
                    var ReachData = result.GetReachesResult; 
                    var ReachStore = new Memory({ data: ReachData, idProperty: "label" });
                    oReachStore = new ObjectStore({ objectStore: ReachStore });
                },
                error: function (err) { }

            });
        },
        GetReaches: function () {
            return oReachStore;
        }
    }

});

calls to module:

Data.Reaches(dataServiceUrl);//set the reach object store
ReachData = Data.GetReaches();//get the reach object store, but is always undefined

Upvotes: 1

Views: 313

Answers (2)

pvitt
pvitt

Reputation: 1065

I needed to use a callback function for the function GetReach. The following modified code worked: Module:

define(['dojo/store/Memory', 'dojo/_base/xhr', "dojo/data/ObjectStore"],
function (Memory, xhr, ObjectStore) {
    return {
        GetReach: function (url, callback) {
            xhr.get({//get data from database
                url: url,
                //url: url,
                handleAs: "json",
                load: function (result) {
                    var ReachData = result.GetReachesResult; 
                    var ReachStore = new Memory({ data: ReachData, idProperty: "label" });
                    var oReachStore = new ObjectStore({ objectStore: ReachStore });
                    callback(oReachStore);
                },
                error: function (err) { }

            });
        }
    }
});

call from main page:

// ....
Data.GetReach(dataServiceUrl, SetReach);
function SetReach(data) {
    //set data for the dropdown
    ddReach.setStore(data);
}

Upvotes: 1

Dimitri Mestdagh
Dimitri Mestdagh

Reputation: 44685

Like you probably noticed by now (by reading your answer), is that you're using an asynchronous lookup (the XMLHttpRequest is asynchronous in this case), but you're relying on that store, before it might be set.

A possible solution is the use of promises/deferreds. I don't know which Dojo version you're using, but in Dojo < 1.8 you could use the dojo/_base/Deferred module and since 1.8 you can use the dojo/Deferred module. Syntax is slightly different, but the concept is the same.

First you change the oReachStore to:

var oReachStore = new Deferred();

Then, inside your Reaches function you don't replace the oReachStore, but you use the Deferred::resolve() function, for example:

return {
    Reaches: function (url) {
        xhr.get({//get data from database
            url: url,
            //url: url,
            handleAs: "json",
            load: function (result) {
                var ReachData = result.GetReachesResult; 
                var ReachStore = new Memory({ data: ReachData, idProperty: "label" });
                oReachStore.resolve(ew ObjectStore({ objectStore: ReachStore })); // Notice the difference
            },
            error: function (err) { }
        });
    },
    GetReaches: function () {
        return oReachStore;
    }
}

Then in your code you could use:

Data.Reaches(dataServiceUrl);//set the reach object store
Data.GetReaches().then(function(ReachData) {
    console.log(ReachData); // No longer undefined
});

So now the ReachData won't return undefined, because you're waiting until it is resolved.

Deferreds are actually a common pattern in the JavaScript world and is in fact a more solid API compared to defining your own callbacks. For example, if you would get an error in your XHR request, you could use:

error: function(err) {
    oReachStore.reject(err);
}

A simple example (I mocked the asynchronous request by using setTimeout()) can be found on JSFiddle: http://jsfiddle.net/86x9n/

Upvotes: 1

Related Questions