So I'm new to working with promises, but I'm having trouble wrapping my head around these asynchronous requests. I am running a QueryTask within a result loop from a FindTask. I am outputting all results to an array, to display once everything finishes up. The issue I am experiencing comes with accessing the results. I can pull out the results from the FindTask with no problem, but when I perform an "execute().then()" statement for my query task, those results are not returned until the promise resolves. However, I would like to access those results sooner (e.g. as soon as that query task is executed). My question is, is there any way to execute a QueryTask without using Promises? Or is there a way to return results immediately within a promise?
My code is posted below for clarification. the goal is to perform a spatial query based off of the returned result of a FindTask, without displaying a map. Any help or tips are much appreciated!
<script>
require([
"esri/tasks/QueryTask",
"esri/tasks/support/Query",
"esri/tasks/FindTask",
"esri/tasks/support/FindParameters",
"dojo/_base/array",
"dojo/dom",
"dojo/on",
"dojo/domReady!"
], function(QueryTask, Query, FindTask, FindParameters, arrayUtils, dom, on) {
var loadingImg = dom.byId("loading");
// Create a FindTask pointing to a map service
var find = new FindTask({
url: "http://gis2.co.frederick.va.us/arcgisweb/rest/services/FC_GIS/FCBase_TEST/MapServer"
});
// Set parameters to only query the point layer by name
var params = new FindParameters({
layerIds: [6],
searchFields: ["ADDRESS"],
returnGeometry: true
});
// Query task REST endpoint for polygon layer to be queried.
var qt = new QueryTask({
url: "http://gis2.co.frederick.va.us/arcgisweb/rest/services/FC_GIS/FCBase_TEST/MapServer/0"
});
resultsarray = [];
// Executes on each button click
function doFind() {
// Display loading gif to provide the user feedback on search progress
loadingImg.style.visibility = "visible";
// Set the search text to the value of the input box
params.searchText = dom.byId("inputAdr").value;
// The execute() performs a LIKE SQL query based on the provided text value
// showResults() is called once the promise returned here resolves
// find.execute(params).then(showResults, rejectedPromise);
find.execute(params)
.then(doGeoQuery)
.otherwise(rejectedPromise);
debugger;
}
function doGeoQuery(response) {
// "response.results" is the data object containing fields and geometry from the found feature
var results = response.results;
arrayUtils.forEach(results, function(findResult, i) {
// Get each value of the desired attributes
var geo = findResult.feature.geometry;
var adr = findResult.feature.attributes.ADDRESS;
var recnum = findResult.feature.attributes.RECNUM;
resultsarray.push(adr);
resultsarray.push(recnum);
console.log("geo",geo);
console.log("adr",adr);
console.log("recnum",recnum);
var spatialquery = new Query();
spatialquery.outFields = ["PIN", "MLNAM"];
spatialquery.geometry = geo;
spatialquery.spatialRelationship = "intersects";
// execute QueryTask
qt.execute(spatialquery).then(function(spatialresults) {
console.log("spatialresults.features", spatialresults.features);
resultsarray.push(spatialresults.features[0].attributes.MLNAM);
resultsarray.push(spatialresults.features[0].attributes.PIN);
console.log("resultsarrayloop",resultsarray);
})
});
debugger;
resultsTable.innerHTML = "";
// If no results are returned from the task, notify the user
if (resultsarray.length === 0) {
resultsTable.innerHTML = "<i>No results found</i>";
loadingImg.style.visibility = "hidden";
return;
}
//console.log("resutls",results);
// Set up row for descriptive headers to display results
var topRow = resultsTable.insertRow(0);
var cell1 = topRow.insertCell(0);
var cell2 = topRow.insertCell(1);
var cell3 = topRow.insertCell(2);
var cell4 = topRow.insertCell(3);
//var cell5 = topRow.insertCell(4);
cell1.innerHTML = "<b>Address</b>";
cell2.innerHTML = "<b>Recnum</b>";
cell3.innerHTML = "<b>MLNAM</b>";
cell4.innerHTML = "<b>PIN</b>";
//cell5.innerHTML = "<b>geometry</b>";
console.log("resultsarray",resultsarray);
debugger;
// Loop through each result in the response and add as a row in the table
arrayUtils.forEach(results, function(findResult, i) {
// Get each value of the desired attributes
var adr = resultsarray[0];
var recnum = resultsarray[1];
var nam = resultsarray[2];
var pin = resultsarray[3];
// Add each resulting value to the table as a row
var row = resultsTable.insertRow(i + 1);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
var cell3 = row.insertCell(2);
var cell4 = row.insertCell(3);
//var cell5 = row.insertCell(4);
cell1.innerHTML = adr;
cell2.innerHTML = recnum;
cell3.innerHTML = nam;
cell4.innerHTML = pin;
//cell5.innerHTML = geo;
debugger;
});
}
var resultsTable = dom.byId("tblAdr");
// Executes each time the promise from find.execute() is rejected.
function rejectedPromise(err) {
console.error("Promise didn't resolve: ", err.message);
debugger;
}
// Run doFind() when button is clicked
on(dom.byId("findBtn"), "click", doFind);
});
</script>
Solved! Go to Solution.
Andrew,
The queryTask returns a promise because it will take some time to make a roundtrip to the server. No you can not get the results right away. You have to develop your code to handle the promise delay. You can do this by placing your the result of your code in the deferred callback or use a dojo "All" to wait for all the deferreds in an array to return and execute the rest of your logic.
Andrew,
The queryTask returns a promise because it will take some time to make a roundtrip to the server. No you can not get the results right away. You have to develop your code to handle the promise delay. You can do this by placing your the result of your code in the deferred callback or use a dojo "All" to wait for all the deferreds in an array to return and execute the rest of your logic.
Good morning Robert,
I was not aware of the dojo/promise/all function, but that looks like exactly what I need. I knew that I wasn't formatting my code in the proper way to deal with promises somehow. Thanks so much for your help!
Glad to help point you in the right direction.
Don't forget to mark this question as answered by clicking on the "Correct Answer" link on the reply that answered your question.