Question

The below function is supposed to use load in a set of JSON files into javascript objects and return them as an array. From my debug I can see that this is all working and doing as it is supposed to although it is executing the load: function(data) last after all other Javascript has finished executing.

So the function executes. Runs the xhr.get 15 times. Returns currentDataSet (empty). Only then the currentDataSet.push(data); within load: function(data) executes populating currentDataSet. At which point it is too late as the return has already run.

require(['dojo/_base/xhr', "dojo/dom", "dojo/date/stamp"], function(xhr, dom){
    generateDataSet = function (startTime) {
        var dataSetFilesNames = generateFilenameSet(startTime);
        var currentDataSet = [];
        for(var j=0; j<15; j++){
            xhr.get({
                url:("/JSONFiles/" + dataSetFilesNames[j]), handleAs:"json",
                load: function(data){
                //The .push statement below is executed 15 times at the end
                    currentDataSet.push(data);
                }
            });
        }
        return currentDataSet;
    }
});

I'll admit this is all new territory for me and I may be misunderstanding how the xhr.get works. I guess the load function executes as the responses come back from the requests. Is there any way that I can get the desired function above to execute in the right order? A way to wait for the response of each xhr.get etc. Open to suggestions.

Thanks in advance.

Was it helpful?

Solution

As you're probably aware, xhr.get happens asynchronously, meaning the code will continue to execute and note wait for it to finish. This is why the order is unpredictable.

Fortunately, this is not a new problem and can be solved using an array of Promises. A Promise interface basically has a handler that will be fired when asynchronous results are returned, whether the call is successful or not. In your case, since you have an array of Promises that you need to handle at once, you can use a function called all.

all (in the case of dojo/promise/all) accepts an array of Promises as input, and executes when all of them have results returned. This means you can use all with a Promise for each of your calls to wait until they're all finished, and then process them. I haven't used dojo/_base/xhr, but I can provide an example using dojo/request/xhr which I'm sure is similar:

var promises = [];
for (var j=0; j<15; j++) {
   var promise = xhr(url, {
         handleAs: "json" 
      }).then({
         function(data){
            // process data, return results here 
         }
      });
   promises.push(promise);
} 

all(promises).then(function(results) {
   // process array of all results here
}); 

I've attached links to all and Promise so you can read about them more.

dojo/promise/all

dojo/promise/Promise

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top