Async issue processing results from Query Task

1844
3
Jump to solution
09-19-2019 07:59 AM
FranklinAlexander
Occasional Contributor III

I have a query widget that queries a view table on ArcGIS REST. In the widget.js file, I am building a whereclause with the widget parameters and using QueryTask to query the database. I need to run two instances of QueryTask, the second takes a lot of time because it has to use statistical results from each row from the 1st query by looping through (67 times) to build an array of rows. [ [...], [...], [...] ]. I then need to format the results of the results array and create a layer. All of this works, except that I am having an async issue. I can't start processing the result array to create the layer until it is done populating. I am going to post a general outline of what I have now and what I have tried, but I won't post all of the code because it is hundreds of lines:

//build whereclause here
...building whereclause...
var queryTask = new QueryTask(tableUrl);
var buckQuery = new Query();
//statistical definitions here (not shown)
buckQuery.returnGeometry = false;
buckQuery.outFields = ["*"];
buckQuery.outStatistics = [statSum, statAvg, statMax, statCount];
buckQuery.orderByFields = ["COUNTY_NAME"];
buckQuery.where = whereclause;
    queryTask.execute(buckQuery).then(function(response) {
	var QueryResults = response.features;
        let resultArr = [];
        for((var i = 0; i < QueryResults.length; i++) {
            let rowSum = null;
            ...more code
            rowSum = [c, stats.FINALSCORESUM, stats.FINALSCOREAVG, stats.COUNTY_COUNT, 
                 countArea, stats.MAXFINALSCORE];
            var queryTask2 = new QueryTask(tableUrl);
	    var buckQuery2 = new Query();
	    buckQuery2.returnGeometry = false;
	    buckQuery2.outFields = ["COUNTY_NAME", "METHOD", "KillDate", "FULLNAME"];
            buckQuery2.where = whereclause2 + " AND FINALSCORE = " + stats.MAXFINALSCORE 
                + " AND COUNTY_NAME = '" + stats.COUNTY_NAME + "'";
            queryTask.execute(buckQuery2).then(function(response) {
	        var QueryResults2 = response.features;
                let stats2 = QueryResults2[0].attributes;
                ... more code
                rowSum.push(stats2.METHOD.toString(), kd, stats2.FULLNAME);
                resultArr.push(rowSum);
            });
         }
     });
if(resultArr !== null || resultArr !== undefined) {
    //here is where I need to do everything else
    //resultArr is undefined
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

This produces an array as described above, but now I need to use that array to create new Formatted Results for the info window and result layer. All of this works fine (I set a timeout to 6 seconds for testing purposes!), I just can't figure out how to keep the javascript from running ahead, and wait on the result array to finish populating. I tried a few things:

First I tried using a Promise/resolve function like this:

 

//build whereclause here
...building whereclause...
var queryTask = new QueryTask(tableUrl);
var buckQuery = new Query();
//statistical definitions here (not shown)
buckQuery.returnGeometry = false;
buckQuery.outFields = ["*"];
buckQuery.outStatistics = [statSum, statAvg, statMax, statCount];
buckQuery.orderByFields = ["COUNTY_NAME"];
buckQuery.where = whereclause;
return new Promise(function(resolve, reject) {
    queryTask.execute(buckQuery).then(function(response) {
	var QueryResults = response.features;
        let resultArr = [];
        for((var i = 0; i < QueryResults.length; i++) {
            let rowSum = null;
            ...more code
            rowSum = [c, stats.FINALSCORESUM, stats.FINALSCOREAVG, stats.COUNTY_COUNT, 
                 countArea, stats.MAXFINALSCORE];
            var queryTask2 = new QueryTask(tableUrl);
	    var buckQuery2 = new Query();
	    buckQuery2.returnGeometry = false;
	    buckQuery2.outFields = ["COUNTY_NAME", "METHOD", "KillDate", "FULLNAME"];
            buckQuery2.where = whereclause2 + " AND FINALSCORE = " + stats.MAXFINALSCORE 
                + " AND COUNTY_NAME = '" + stats.COUNTY_NAME + "'";
            queryTask.execute(buckQuery2).then(function(response) {
	        var QueryResults2 = response.features;
                let stats2 = QueryResults2[0].attributes;
                ... more code
                rowSum.push(stats2.METHOD.toString(), kd, stats2.FULLNAME);
                resultArr.push(rowSum);
            });
         }
     });
}).then(function(resultArr) {
     showResults(resultArr);
});

function showResults(resultArr) {
    ...
}

but this didn't solve the issue. The showResults function executes without waiting and once again I get undefined for the result array. I also tried using a simple callback:

function getQueryResultsAndBuildArray (whereclause, callback)
//this is the same function as above so I won't paste it
    ...code goes here
    callback(resultArr);
}

function showResults(resultArr) {
    ....
}

getQueryResultsAndBuildArray (whereclause, showResults);
    

Got the exact same result, undefined when executing the showResults function. Just looking for some input on what I am doing wrong and maybe a better way to approach.

Thanks!!

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Franklin,

  You need to use dojo/promise/all.

View solution in original post

3 Replies
RobertScheitlin__GISP
MVP Emeritus

Franklin,

  You need to use dojo/promise/all.

FranklinAlexander
Occasional Contributor III

Robert,

Thanks, I am going to try that. I was able to get it working by getting a count of the results from the first query and then using a counter to count the loops, and when they matched, I executed the showResults function. I am going to try your way as well because it's probably the 'correct' method and I'm not sure it there are any pitfalls to the method I used.

Thanks!

0 Kudos
ManuelValderrama
New Contributor

hi,

you can do this...
    fuctionInWidget: async function (ID) {
      var attr = await attributes(ID);
      
      async function attributes(id){
        var query = new Query();
        query.where ="OBJECTID = " + id;
        query.outFields = ["*"];

        var queryTask = new QueryTask("stringURL");
        var response = queryTask.execute(query);
        var fs = await response.promise;
        
        return fs.features[0].attributes
      };
      
      insertRowInTabe(attr);
      function insertRowInTabe(attributes){
        var featureRow = domConstruct.create("tr"null"tableBody");
        attributes.forEach(attribute => {
          var fieldCell = featureRow.insertCell(0);
          fieldCell.innerHTML = attribute;
        })
      };
    },
0 Kudos