I would agree with Derek and Steve; you need to be careful not to overwhelm the user experience with too much information. Keep it simple and only retrieve data from the server when necessary. Below is an example of how you can use dojo.Deferred and dojo.DeferredList to properly associate responses/results and the sources of the queries.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=7,IE=9" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
<title>Get Counties By State</title>
<link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/2.4/js/dojo/dijit/themes/claro/claro.css">
<script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.4"></script>
<script type="text/javascript">
dojo.require("esri.map");
dojo.require("esri.tasks.query");
dojo.require("dojo.DeferredList");
function init() {
var map = new esri.Map("map");
var imageParameters = new esri.layers.ImageParameters();
imageParameters.format = "jpeg";
var dynamicMapServiceLayer = new esri.layers.ArcGISDynamicMapServiceLayer("http://services.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Population_Density/MapServer", {
"imageParameters": imageParameters
});
map.addLayer(dynamicMapServiceLayer);
//
// GET STATE FEATURES
//
getStates(dynamicMapServiceLayer, 4);
}
// GET STATE FEATURES
function getStates(layer, subLayerIndex) {
var statesQueryDeferred = doQuery(layer, subLayerIndex, '1=1')
statesQueryDeferred.then(function(statesFeatueSet) {
// BUILD LIST OF QUERY WHERE STRINGS
var whereClauses = dojo.map(statesFeatueSet.features, function(statesFeature) {
return {
stateName: statesFeature.attributes.ST_ABBREV,
where: dojo.replace("ST_ABBREV = '{attributes.ST_ABBREV}'", statesFeature)
};
});
getCountiesByState(layer, 3, whereClauses);
});
}
//
// GET COUNTY COUNT FOR EACH STATE
//
function getCountiesByState(layer, subLayerIndex, whereClauses) {
// CREATE ARRAY OF DEFERREDS
var countiesDeferredArray = dojo.map(whereClauses, function(whereClause) {
// CREATE STATE NODE
var stateNode = dojo.create('div', {
'innerHTML': dojo.replace("{stateName} - ", whereClause)
}, 'countyInfo');
var countyCountNode = dojo.create('span', {
'id': dojo.replace("countyCount_{stateName}", whereClause),
'innerHTML': 'Searching...'
}, stateNode);
// RETURN QUERY DEFERRED
return doQuery(layer, subLayerIndex, whereClause.where);
}, this);
// CREATE DEFERRED LIST FROM ARRAY OF DEFERREDS
var countiesDeferredList = new dojo.DeferredList(countiesDeferredArray);
countiesDeferredList.then(function(responses) {
// WE GET ONE RESPONSE WHEN THEY'RE ALL DONE
dojo.forEach(responses, function(response, responseIndex) {
// FIND MATCHING WHERE CLAUSE
var whereClause = whereClauses[responseIndex];
// FIND STATE NODE
var stateNode = dojo.byId(dojo.replace("countyCount_{stateName}", whereClause));
// DO WE HAVE A SUCCESSFUL RESPONSE
if(response[0]) {
var countyFeatureSet = response[1];
// UPDATE STATE NODE WITH COUNTY COUNT
stateNode.innerHTML = dojo.replace("{features.length} counties", countyFeatureSet);
} else {
stateNode.innerHTML = 'Error...';
}
}, this);
});
}
//
// QUERY
//
function doQuery(layer, subLayerIndex, where) {
var query = new esri.tasks.Query();
query.returnGeometry = false;
query.outFields = ["*"]
query.where = where;
var queryTask = new esri.tasks.QueryTask(layer.url + "/" + subLayerIndex);
return queryTask.execute(query);
}
dojo.addOnLoad(init);
</script>
</head>
<body class="claro">
<div id="map" style="width:500px; height:300px; border:1px solid #000;"></div>
<ul id="countyInfo"></ul>
</body>
</html>