Select to view content in your preferred language

queryTask.executeForCount causes error messages when used repeatedly

2917
3
05-04-2011 10:44 PM
StephenLead
Honored Contributor
I'm trying to build some logic which will switch layers on/off based on feature count (rather than scale thresholds).

After each map extent change, I'm running queryTask.executeForCount to see how many features are present in the new view extent. This works correctly, but causes a problem when the user changes extent many times in quick succession.

See the sample below for an example. Open FireBug and pan/zoom the map, and note that the number of features in the current map extent is listed in the Console tab.

Now hit the zoom-in button about 10 times in rapid succession. I'm seeing time-out error messages.

Is this a limitation of the queryTask, which presumably batches all of the jobs to run asynchronously? Any ideas on how to resolve the problem?

Thanks,
Steve

<!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"/>
    <!--The viewport meta tag is used to improve the presentation and behavior of the samples
      on iOS devices-->
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
    <title>FeatureLayer with count</title>
    <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/2.2/js/dojo/dijit/themes/claro/claro.css">
    <style>
      html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
    </style>
    <script type="text/javascript">djConfig = { parseOnLoad:true };</script>
    <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.2"></script>
    <script type="text/javascript">
      dojo.require("esri.map");
      dojo.require("esri.layers.FeatureLayer");
      dojo.require("dijit.form.Button");
      dojo.require("dijit.Dialog");

   var query;
   var queryTask;
      
      function init() {
        var extent = new esri.geometry.Extent({"xmin":-96.6063,"ymin":38.3106,"xmax":-96.4764,
              "ymax":38.3689,"spatialReference":{"wkid":4269}});
        var map = new esri.Map("map", { extent: esri.geometry.geographicToWebMercator(extent)});
        
  veTileLayer  = new esri.virtualearth.VETiledLayer({
   bingMapsKey: 'AmtpLvkTJh3qNOm_vTV4DIXQ0ucCWYI0hrcO4wARRegSC79rstkDrYghY70pjoxY',
   mapStyle: esri.virtualearth.VETiledLayer.MAP_STYLE_ROAD
  });
  map.addLayer(veTileLayer);

        var content = "<b>Type</b>: ${ftype}" + "<br /><b>Code</b>: ${fcode}";
        var infoTemplate = new esri.InfoTemplate("Rivers", content);
        
        featureLayer = new esri.layers.FeatureLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hydrography/Watershed173811/FeatureServer/1",{
          mode: esri.layers.FeatureLayer.MODE_ONDEMAND,
          outFields: ["*"],
          infoTemplate: infoTemplate
        });
        map.addLayer(featureLayer);
        
        dojo.connect(map, "onExtentChange", afterExtentChange);
        query = new esri.tasks.Query();
        
      }
      
      function afterExtentChange(extent){

            //Count the SLAs
            query.geometry = extent;   
            query.maxAllowableOffset = 100000;         
            queryTask = new esri.tasks.QueryTask("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hydrography/Watershed173811/FeatureServer/1");            
            queryTask.executeForCount(query,function(count){
              console.log(count);
            },function(error){
              console.log(error);
            });
        }
                    
      dojo.addOnLoad(init);
      
    </script>
  </head>
  <body class="claro">
    <div style="position:relative;width:100%;height:100%;">
      <div id="map" style="border:1px solid #000;width:100%;height:100%;">
      </div>
    </div>
  </body>
</html>
0 Kudos
3 Replies
HemingZhu
Frequent Contributor
I'm trying to build some logic which will switch layers on/off based on feature count (rather than scale thresholds).

After each map extent change, I'm running queryTask.executeForCount to see how many features are present in the new view extent. This works correctly, but causes a problem when the user changes extent many times in quick succession.

See the sample below for an example. Open FireBug and pan/zoom the map, and note that the number of features in the current map extent is listed in the Console tab.

Now hit the zoom-in button about 10 times in rapid succession. I'm seeing time-out error messages.

Is this a limitation of the queryTask, which presumably batches all of the jobs to run asynchronously? Any ideas on how to resolve the problem?

Thanks,
Steve

<!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"/>
    <!--The viewport meta tag is used to improve the presentation and behavior of the samples
      on iOS devices-->
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
    <title>FeatureLayer with count</title>
    <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/2.2/js/dojo/dijit/themes/claro/claro.css">
    <style>
      html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
    </style>
    <script type="text/javascript">djConfig = { parseOnLoad:true };</script>
    <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.2"></script>
    <script type="text/javascript">
      dojo.require("esri.map");
      dojo.require("esri.layers.FeatureLayer");
      dojo.require("dijit.form.Button");
      dojo.require("dijit.Dialog");

   var query;
   var queryTask;
      
      function init() {
        var extent = new esri.geometry.Extent({"xmin":-96.6063,"ymin":38.3106,"xmax":-96.4764,
              "ymax":38.3689,"spatialReference":{"wkid":4269}});
        var map = new esri.Map("map", { extent: esri.geometry.geographicToWebMercator(extent)});
        
  veTileLayer  = new esri.virtualearth.VETiledLayer({
   bingMapsKey: 'AmtpLvkTJh3qNOm_vTV4DIXQ0ucCWYI0hrcO4wARRegSC79rstkDrYghY70pjoxY',
   mapStyle: esri.virtualearth.VETiledLayer.MAP_STYLE_ROAD
  });
  map.addLayer(veTileLayer);

        var content = "<b>Type</b>: ${ftype}" + "<br /><b>Code</b>: ${fcode}";
        var infoTemplate = new esri.InfoTemplate("Rivers", content);
        
        featureLayer = new esri.layers.FeatureLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hydrography/Watershed173811/FeatureServer/1",{
          mode: esri.layers.FeatureLayer.MODE_ONDEMAND,
          outFields: ["*"],
          infoTemplate: infoTemplate
        });
        map.addLayer(featureLayer);
        
        dojo.connect(map, "onExtentChange", afterExtentChange);
        query = new esri.tasks.Query();
        
      }
      
      function afterExtentChange(extent){

            //Count the SLAs
            query.geometry = extent;   
            query.maxAllowableOffset = 100000;         
            queryTask = new esri.tasks.QueryTask("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hydrography/Watershed173811/FeatureServer/1");            
            queryTask.executeForCount(query,function(count){
              console.log(count);
            },function(error){
              console.log(error);
            });
        }
                    
      dojo.addOnLoad(init);
      
    </script>
  </head>
  <body class="claro">
    <div style="position:relative;width:100%;height:100%;">
      <div id="map" style="border:1px solid #000;width:100%;height:100%;">
      </div>
    </div>
  </body>
</html>


There are scenarios that you will get such messages. One example: suppose you set up 4 pooled instances for your map services, and the maximum time a client will wait to get a service is 60 seconds (default). When 4 pooled instances are being used, the next query request has to wait until one instance are free for use. So chance is increasing that waiting time for one or more query request will exceed 60 seconds when so many panning (request) are going on... Besides, request timeout via JS API itself is set up 60 second as default... Other consideration would be network traffic or SDE etc.  So you have to weigh in these factors to either adjust your settings or change a code logic..
0 Kudos
derekswingley1
Deactivated User
Since executeForCount returns a dojo.Deferred, I wonder if you could keep a reference to these and cancel previous, unresolved queryTasks before firing off a new query when the client does something (e.g. zoom in ten times quickly) that causes a lot of these to be fired. Just thinking out loud here...I haven't actually tried this.
0 Kudos
derekswingley1
Deactivated User
I did a little testing and it looks like these errors are related to the feature layer, not your query task. I vaguely remember seeing something like this shortly after feature layers landed in the JS API but don't recall ever finding a solution.
0 Kudos