Executing a series of queries inside a loop

4062
6
Jump to solution
05-05-2016 12:06 PM
Highlighted
Occasional Contributor

Hello,

I am trying to loop through a string array of place names, build a query statement for each place, get the extent for the place, and build a bookmarks list. I am however baffled with how the results are built. Basically, it looks like while the query task is located inside the loop, it waits for the loop to finish to be executed. Therefore I get multiple and identical query results in the end. The core of the problem can be shown with this piece of code:

for (i = 1; i < allSysNames.length; i++) {

     query.where = "SysName =" + allSysNames;

     console.log("i inside the loop is: " + i);

     queryTask.executeForExtent(query, function(result){

          console.log("i inside query task equals to: " + i);

     });

}

console.log("outside the loop");

The log is the following.

i inside the loop is: 1

i inside the loop is: 2

i inside the loop is: 3

outside the loop

i inside query task equals to 4

i inside query task equals to 4

i inside query task equals to 4

I am probably missing something very basic here, as I am new to Javascript and the API. What do I need to execute the queryTask for my purposes? Thank you!

Naci

Reply
0 Kudos
1 Solution

Accepted Solutions
Highlighted
Frequent Contributor

Those query tasks are asynchronous, so won't be executed immediately.

You have a couple of options

var queries = [];

for (i = 1; i < allSysNames.length; i++) {

    query.where = "SysName =" + allSysNames;

    console.log("i inside the loop is: " + i);

    queries.push(queryTask.executeForExtent(query));

}

// dojo/promise/all

all(queries).then(, function(results){

    // another for loop

    for (var j = 0; j < results.length; j++) {

        console.log("j inside query task equals to: " + j);

    }

});

console.log("outside the loop");

// or

// I prefer this method

var queries = allSysNames.map(function(name) {

    query.where = "SysName =" + name;

    return queryTask.executeForExtent(query)

});

// dojo/promise/all

all(queries).then(, function(results){

    // another for loop

    for (var j = 0; j < results.length; j++) {

        console.log("j inside query task equals to: " + j);

    }

});

console.log("outside the loop");

I have a couple of posts on Promises you could check out.

Keeping Promises

ArcGIS JavaScript Promises - odoenet

Since the Promises is asynchronous, it will finish after your last console statement.

Hope that helps a bit.

View solution in original post

6 Replies
Highlighted
Frequent Contributor

Those query tasks are asynchronous, so won't be executed immediately.

You have a couple of options

var queries = [];

for (i = 1; i < allSysNames.length; i++) {

    query.where = "SysName =" + allSysNames;

    console.log("i inside the loop is: " + i);

    queries.push(queryTask.executeForExtent(query));

}

// dojo/promise/all

all(queries).then(, function(results){

    // another for loop

    for (var j = 0; j < results.length; j++) {

        console.log("j inside query task equals to: " + j);

    }

});

console.log("outside the loop");

// or

// I prefer this method

var queries = allSysNames.map(function(name) {

    query.where = "SysName =" + name;

    return queryTask.executeForExtent(query)

});

// dojo/promise/all

all(queries).then(, function(results){

    // another for loop

    for (var j = 0; j < results.length; j++) {

        console.log("j inside query task equals to: " + j);

    }

});

console.log("outside the loop");

I have a couple of posts on Promises you could check out.

Keeping Promises

ArcGIS JavaScript Promises - odoenet

Since the Promises is asynchronous, it will finish after your last console statement.

Hope that helps a bit.

View solution in original post

Highlighted
MVP Honored Contributor

One more useful thing to know about Promises is that they are returned in the same order that they are passed in. Therefore, you'll always know that result1 will be what's returned from query1, result2 will be what's returned from query2, etc

Highlighted
Occasional Contributor

Thank you very much! This helps a lot. I have a couple of follow up questions. First, Aptana gives me an error for the use of comma in this line

all(queries).then(, function(results){

I removed the comma, and it seems to be working fine. Is that OK?

Second issue is another one that confuses me. As I mentioned before, I use this loop to build a bookmarks list (following this example Bookmarks widget | ArcGIS API for JavaScript), which I defined as

bookmarks = new esri.dijit.Bookmarks({

    map: map,

}, dojo.byId('bookmarks'));

I then created a temp bookmark:

var tempBookmark ={

          "extent": {

            "spatialReference": {

                "wkid": 0

            },

            "xmin":0,

            "ymin":0,

            "xmax":0,

            "ymax":0

          },

          "name": "Temp"

      };

In the procedure you described, I assigned the extents of the results to the tempBookmark. I also assigned the tempBookmark name using allSysNames. Here is the more complete piece of the code:

all(queries).then(function(results){

    // another for loop

    for (var j = 0; j < results.length; j++) {

          console.log("j inside query task equals to: " + j);

          console.log(results.extent);

          tempBookmark.extent = results.extent;

          tempBookmark.name = allSysNames;

          console.log(tempBookmark.extent);

          bookmarks.addBookmark(tempBookmark);

}

});

So the bookmark list is built just fine, with the correct names from the allSysNames array. Apparently the statement tempBookmark.name = allSysNames; works as expected. However the problem is with the actual extents. I have 5 items in the bookmarks list, and no matter which one I click, it zooms to the extents of the last item in the array. For debugging purposes I logged the values of the elements (xmin, xmax, ymin, ymax) of tempBookmark.extent, and they are same as corresponding results.extent values. But those values apparently do not properly get transferred to the bookmarks. It is strange because the bookmark name appears to be updated just fine.

Reply
0 Kudos
Highlighted
Frequent Contributor

For the first one, that was a typo on my part, sorry.

For second one

The tempBookmark you are updating is a single bookmark, so you keep updating the same one and adding it multiple times, but inside the bookmark widget, you basically added the same bookmark multiple times.

Create a new bookmark on each loop and you should be ok.

Highlighted
Occasional Contributor

Thanks a lot, that solved my problem!

Reply
0 Kudos
Highlighted
New Contributor III

Hi Rene,

Why doesn't this work? Where visible is coming from an array of layerId's that are providing indexes for myQuery (it works for any random array eg ["alpha", "beta", "charlie"]:

var myQuery = ["Population>10000" , "Hispanic > 1500" , "Employees > 10000"];

var result = visible.map(function(e) {
return myQuery;
});

Reply
0 Kudos