A query task is the ideal choice for getting a small number of features from a single layer in a map service. Occasionally, it is necessary to query multiple layers simultaneously. If the requirement is to query all layers in a map service, then an identify task should be used. Otherwise, it can be useful to use multiple query tasks to query different layers. The potential hangup with this approach is how to know when all queries have finished. The answer is to use a dojo/promise/all. Using an instance of dojo/promise/all is an easy way to be notified when multiple promises or deferreds finish. dojo/promise/all is created by passing an array of promises or deferred. This is trivial when using queryTasks since the return value of a queryTask is a deferred. Once all the deferreds are resolved, the results are passed to a callback. Inside the callback, all results can be processed.
The code in the sample shows an exmaple of how this would work: initially, two queries and two query task objects are created. When the map is clicked, both query tasks are executed and an instance of dojo/promise/all is created using them. When both queries finish, all results are passed to the callback and the features returned are added to the map.
This sample also shows how to build an extent from a map click point.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"> <title>Manage results from multiple queries</title> <link rel="stylesheet" href="https://js.arcgis.com/3.46/dijit/themes/tundra/tundra.css"> <link rel="stylesheet" href="https://js.arcgis.com/3.46/esri/css/esri.css"> <style> html, body { height: 100%; width: 100%; margin: 0; padding: 0; } #map{ margin: 0; padding: 0; } #controls { position: absolute; height: 80px; font-family: arial; bottom: 10px; margin: 5px; padding: 5px; z-index: 40; background: #fff; color: #444; width: 440px; left: 10px; -moz-box-shadow: 0 0 5px #888; -webkit-box-shadow: 0 0 5px #888; box-shadow: 0 0 5px #888; } h3 { margin: 0 0 5px 0; border-bottom: 1px solid #444; } .label { display: inline-block; width: 140px; } </style> <script src="https://js.arcgis.com/3.46/"></script> <script> var app = {}; require([ "dojo/parser", "dojo/promise/all", "dojo/_base/connect", "esri/Color", "dojo/_base/array", "dojo/dom", "esri/config", "esri/map", "esri/geometry/Extent", "esri/symbols/SimpleFillSymbol", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/tasks/query", "esri/tasks/QueryTask", "dijit/layout/BorderContainer", "dijit/layout/ContentPane", "dojo/domReady!" ], function( parser, all, connect, Color, arrayUtils, dom, esriConfig, Map, Extent, SimpleFillSymbol, ArcGISDynamicMapServiceLayer, Query, QueryTask ) { // create layout dijits parser.parse(); app.map = new Map("map"); var basemap = new ArcGISDynamicMapServiceLayer("https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer"); app.map.addLayer(basemap); // query task and query for COUNTIES app.qt1 = new QueryTask("https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/3"); app.q1 = new Query(); // query task and query for STATES app.qt2 = new QueryTask("https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/2"); app.q2 = new Query(); app.q1.returnGeometry = app.q2.returnGeometry = true; app.q1.outFields = app.q2.outFields = ["*"]; app.map.on("click", executeQueries); function executeQueries(e) { var counties, states, promises, qGeom, point, pxWidth, padding; // create an extent from the mapPoint that was clicked // this is used to return features within 3 pixels of the click point point = e.mapPoint; pxWidth = app.map.extent.getWidth() / app.map.width; padding = 3 * pxWidth; qGeom = new Extent({ "xmin": point.x - padding, "ymin": point.y - padding, "xmax": point.x + padding, "ymax": point.y + padding, "spatialReference": point.spatialReference }); // use the extent for the query geometry app.q1.geometry = app.q2.geometry = qGeom; counties = app.qt1.execute(app.q1); states = app.qt2.execute(app.q2); console.log("deferreds: ", counties, states); promises = all([counties, states]); promises.then(handleQueryResults); console.log("created d list"); } function handleQueryResults(results) { console.log("queries finished: ", results); var counties, states; // make sure both queries finished successfully if ( ! results[0].hasOwnProperty("features") ) { console.log("Query 1 failed."); } if ( ! results[1].hasOwnProperty("features") ) { console.log("Query 2 failed."); } // results from deferred lists are returned in the order they were created counties = results[0].features; states = results[1].features; app.map.graphics.clear(); // add the results to the map arrayUtils.forEach(counties, function(feat) { feat.setSymbol(new SimpleFillSymbol()); app.map.graphics.add(feat); }); arrayUtils.forEach(states, function(feat) { feat.setSymbol( new SimpleFillSymbol() .setColor(new Color([255, 0, 255, 0.5])) .setOutline(null) ); app.map.graphics.add(feat); }); dom.byId("results").innerHTML = "Number of counties: " + counties.length + "<br />Number of states: " + states.length; } }); </script> </head> <body class="tundra"> <div data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design:'headline',gutters:false" style="width: 100%; height: 100%; margin: 0;"> <div id="map" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'center'"> <div id="controls"> <h3>Multiple Query Tasks</h3> <div id="results">Click the map to query multiple layers.</div> </div> </div> </div> </body> </html>