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.
Solved! Go to Solution.
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);
}
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?
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.
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.
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.
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.
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);
}