how to capture results of 'nearme' widget query

254
6
Jump to solution
04-09-2019 11:49 AM
FranklinAlexander
Occasional Contributor II

I thought this would be very straight forward, but it has turned into an extremely challenging task. I am using the nearme widget to capture features from a polygon layer. The resulting feature attributes can then be used as a filter for an attribute query in a web form. I just need to capture the features, loop through that attributes and return an array of id's, one for each feature. Sounds simple enough, except that it can take up to 8 seconds for the results to populate, depending on the size of the buffer used. I am trying to set up a promise function to wait for the results, and then once captured I can loop through the array and return the ids. I can't seem to get this to work, I just undefined. I think the problem is that it is hard to determine exactly when the results have finished populating. This is what I have tried:

_getResultsArray: function(itemList) {
        console.log("item list object ", itemList); //is defined!!
        var wmaArray = null;
        var def = new Deferred();
        if (itemList) {
            wmaArray = itemList._searchedFeatures['Wildlife Management Areas'];
            console.log("WMAs ", wmaArray);
            def.resolve(wmaArray);
        }
        console.log("wma array ", def);
        return def.promise;
},

//the above function is called in the _CreateBuffer() function

this._getResultsArray(this._itemListObject).then(lang.hitch(this, function(wmaArray){
          console.log("WMAs ", wmaArray); ///returns undefined. Is not waiting for result
}));

‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I have also tried this without getting any result: 

this.own(on(this._itemListObject, "load", lang.hitch(this, function () {
    var wmaArray = itemList._searchedFeatures['Wildlife Management Areas'];
    console.log("WMAs ", wmaArray); //nothing gets logged
})));

This only way I can get the results is by setting a timeout, but this is not a good solution. Even if I set it for 8 seconds, I can still get be undefined if there are a lot of returns! Additionally, if there are only a couple of results, that can be a big problem as well.

setTimeout(function() {
    var wmaArray = itemList._searchedFeatures['Wildlife Management Areas'];
    console.log("WMAs ", wmaArray);
}, 8000);

//this returns an array of features, which is just what I need, but I need a better solution!!‍‍‍‍‍‍‍‍‍‍‍‍

Can anyone see what is wrong with the first solution? Am I going about the the wrong way?

Thanks for any advice.

1 Solution

Accepted Solutions
FranklinAlexander
Occasional Contributor II

Thanks for the suggestions, but I never did get a promise to work no matter what I tried. I know I am leaving out something important, but for now promises are Greek to me. I did find a much simpler solution, however. I knew that there had to be an existing variable some place in one of the js files that already contained the features list, and once I found it (finally!), the rest was a piece of cake!!  Sometimes I like to make a mountain out of a molehill. 

In the item-list.js file:

var PHGA_array = [];

if (featureSet.features.length > 0) {
      this._showFilteredFeaturesOnLoad(featureSet.features, this._selectedLayer.id);
       //creates feature list
       this._creatFeatureList(featureSet.features); 
        var wmaArray = featureSet.features;
        wmaArray.forEach(function(feature) {
              var id = feature.attributes.PHGA_ID;
              PHGA_array.push(id);
         });
         console.log("PHGA Array ", PHGA_array);
}

View solution in original post

0 Kudos
6 Replies
RobertScheitlin__GISP
MVP Esteemed Contributor

Franklin,

   It sounds like the 

itemList._searchedFeatures

is not populated before you attempt to use it. What does the function that populates itemList.searchedFeatures look like?

0 Kudos
FranklinAlexander
Occasional Contributor II

Robert,

The _searchedFeatures are part of the _itemListObject. What is weird is that I can log out the _itemListObject and it appears that the _searchedFeatures and the "Wildlife Maganagement Areas" are there almost immediately. But when I try and get to the WMAs directly with the code: 

var itemList = _itemListObject;
var wmaArray = itemList._searchedFeatures['Wildlife Management Areas'];
console.log("WMAs ", wmaArray);

Here is what I am seeing in the console when I log out _itemsListObject:

Do I need to access the _searchedFeatures first before trying to access the "Wildlife Management Areas"? I didn't think it would make much difference. I guess I thought I could just try and go straight to the WMAs and wait for the result before executing and next function.

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Franklin,

   You have made the mistake many JS developer have early on. Just because you can console log something does not mean that that something is ready when your code is attempting to access it. The thing is console is like an async process it will show your the details of something when they get set though they may have been null a cpu cycle earlier.

FranklinAlexander
Occasional Contributor II

Yes, I totally forgot! But I am still confused as to how to get js to wait until the results are ready. Should I be trying to use a promise.then(), or is there a better way? Honestly, I am still trying to wrap my head around promises, and I have never really been able to get one to actually work! They always seem to NOT wait. 

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Franklin,

   The way you are using the Deferred in your code is fine. But now you need to use a deferred some way when you populate the itemList._searchedFeatures that way you do not call the _getResultsArray until the searchedfeature is actually ready.

0 Kudos
FranklinAlexander
Occasional Contributor II

Thanks for the suggestions, but I never did get a promise to work no matter what I tried. I know I am leaving out something important, but for now promises are Greek to me. I did find a much simpler solution, however. I knew that there had to be an existing variable some place in one of the js files that already contained the features list, and once I found it (finally!), the rest was a piece of cake!!  Sometimes I like to make a mountain out of a molehill. 

In the item-list.js file:

var PHGA_array = [];

if (featureSet.features.length > 0) {
      this._showFilteredFeaturesOnLoad(featureSet.features, this._selectedLayer.id);
       //creates feature list
       this._creatFeatureList(featureSet.features); 
        var wmaArray = featureSet.features;
        wmaArray.forEach(function(feature) {
              var id = feature.attributes.PHGA_ID;
              PHGA_array.push(id);
         });
         console.log("PHGA Array ", PHGA_array);
}
0 Kudos