Managing a deferred list of query tasks

Discussion created by schlot on Aug 8, 2013
Latest reply on Aug 9, 2013 by schlot
My goal is to select a legislative district by number, using it's geometry as input to look up different features in that district. There will be lots of different layers the user can turn on/off (schools, nursing homes etc) and the query will select only those features that are currently visible within their district and create a list.    The query tasks must therefore be generated on the fly.

I am using a posted Fiddle example for a deferred list for identifytasks, modifying it for query tasks instead.  (Thanks Brett for such a great example BTW) I have made good progress up to a point, I see that each of my queries are executing.  But I'm getting bogged down in how to manage the multiple sets of results that are getting returned as output from each of the tasks.

I have an empty array defined as qTaskList to hold all the query tasks needed for the current visibility.
qTaskList = [];

In previous functions I have defined a single Query, called multiQuery that will be used for all the queryTasks I execute.  It is defined as:

multiQuery = new esri.tasks.Query();

   multiQuery.outSpatialReference = map.spatialReference; 
   multiQuery.returnGeometry = false;
   multiQuery.spatialRelationship = esri.tasks.Query.SPATIAL_REL_CONTAINS; 
   multiQuery.outFields = ["*"];

These are supposed to generate a set of querytasks, which as put in a deferredlist and then executed. 

function runQueries(geometry) {
    multiQuery.geometry = geometry;
    //Create an array of all layers in the map
    var layers =, function(layerId) {
      return map.getLayer(layerId);
    layers = dojo.filter(layers, function(layer) {
        return layer.getImageUrl && layer.visible;
    }); //Only dynamic layers have the getImageUrl function. Filter so you only query visible dynamic layers
     var qtasks = generateQTasks(layers);
    var defTasks =, function (task) {
        return new dojo.Deferred();
    }); //map each query task to a new dojo.Deferred
    var dlTasks = new dojo.DeferredList(defTasks); //And use all of these Deferreds in a DeferredList
      dlTasks.then(showQueryResults); //chain showQueryResults onto your DeferredList

          for (i=0;i<qtasks.length;i++) { //Use 'for' instead of '' so you can sync tasks with defTasks
        try {
            qtasks[i].execute(multiQuery, defTasks[i].callback, defTasks[i].errback); //Execute each task
        } catch (e) {
            console.log("Error caught");
            defTasks[i].errback(e); //If you get an error for any task, execute the errback
//function used to determine which layer visibility of each ArcGISDynamicMapServiceLayer
function generateQTasks(layers) {
   qTaskList.length = 0;, function (layer){

        if ( !== "districtLayer") {//don't run querytasks against the layer used in the findtask, it's not needed

         var visLayers = getVisibleLayers(layer);
          dojo.forEach(visLayers, function (layerId){
            var qTask = new esri.tasks.QueryTask(layer.url+"/"+layerId);
    return qTaskList;

function getVisibleLayers(myLayer) {    
var visibleLayers = [];
    var items =, function (info, index) {
        layerID =;
        if (info.visible && !info.subLayerIds) {
    return visibleLayers;

This is where I start to get lost.  I've added break points and it does look that I have an array, successResults, each of which is a featureSet (I think!).  But when I try to process these individually, it only seems to process the first featureSet, not all of them.  I know I also have issues in the next function, queryGeometryResultsHandler_toGrid, which is supposed to generate a titlePane in a div for each out the ouput.  Probably that will be a whole other thread!  For now all I'm trying to do is properly deal with my array of featureSets.
function showQueryResults (queryResults) {
        var successResults = [];
    queryResults = dojo.filter(queryResults, function (result) {
        return queryResults[0];
    }); //filter out any failed tasks
    for (i=0;i<queryResults.length;i++) {
        successResults = successResults.concat(queryResults[i][1]);//these are all the successful querytasks
 numberQueryTasks = successResults.length;
//need to process each set of query results
    dojo.forEach(successResults, function(taskResults) {
 console.log("within dojo foreach of successResults");