0

I am facing the following synchronization issue. I wouldn't be surprised if it has a simple solution/workaround. The BuildMenu() function is called from another block of code and it calls the CreateMenuData() which makes a request to a service which return some data. The problem is that since it is an async call to the service when the data variable is being used it is undefined. I have provided the js log that also shows my point.

        BuildMenu: function () {
            console.log("before call");
            var data=this.CreateMenuData();
            console.log("after call");
            //Doing more stuff with data that fail.
        }


CreateMenuData: function () {
        console.log("func starts");
        data = [];
        dojo.forEach(config.layerlist, function (collection, colindex) {

            var layersRequest = esriRequest({
                url: collection.url,
                handleAs: "json",
            });

            layersRequest.then(
                function (response) {
                    dojo.forEach(response.records, function (value, key) {
                        console.log(key);
                        data.push(key);


                    });

                }, function (error) {

                });

        });
        console.log("func ends");
        return data;
    }

   Console log writes:
   before call
   func starts
   func ends
   after call
   0
   1
   2
   3
   4
  • possible duplicate of [How to return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Ken Franqueiro Sep 07 '15 at 01:43

1 Answers1

0

FYI: using anything "dojo." is deprecated. Make sure you are pulling all the modules you need in "require".

Ken has pointed you the right direction, go through the link and get familiarized with the asynchronous requests.

However, I'd like to point out that you are not handling only one async request, but potentionally there might be more of them of which you are trying to fill the "data" with. To make sure you handle the results only when all of the requests are finished, you should use "dojo/promise/all".

CreateMenuData: function (callback) {
        console.log("func starts");
        requests = [];
        data = [];
        var scope = this;

        require(["dojo/_base/lang", "dojo/base/array", "dojo/promise/all"], function(lang, array, all){
            array.forEach(config.layerlist, function (collection, colindex) {
                var promise = esriRequest({
                    url: collection.url,
                    handleAs: "json",
                });
                requests.push(promise);
            });

            // Now use the dojo/promise/all object
            all(requests).then(function(responses){
                // Check for all the responses and add whatever you need to the data object.
                ...
                // once it's all done, apply the callback. watch the scope! 
                if (typeof callback == "function")
                    callback.apply(scope, data);

            });
        });        
    }

so now you have that method ready, call it

BuildMenu: function () {
    console.log("before call");

    var dataCallback = function(data){
        // do whatever you need to do with the data or call other function that handles them.       
    }

    this.CreateMenuData(dataCallback);  
}
belzebu
  • 810
  • 7
  • 25