Select to view content in your preferred language

Second QueryTask Runs before First One Completes - How to Get Results from First

803
4
Jump to solution
01-09-2013 05:15 AM
chuckfrank
Frequent Contributor
Hi All,

In an effort to write reusable code, I wrote the function below that will query a feature layer (url paramater) by a polygon (poly parameter).  This way I don't need to have a separate query and actionscript block for each feature layer that I'll query.  The problem that will happen is that when the function is called multiple times in a row the second query will begin before the first one has completed because it's asynchronous.  At that point I'm not sure how to know which result is which.  I really want to avoid having to write a black of code for each specific query, but when I try to generalize it, like the example below, I'm running into the asynchonous issues.  Does any body have any ideas to handle this or a code example of a better way?  Is there a way I can understand which result is which?

Thanks,
Chuck

  private function FilterAttributeTablesByPolygon(poly:Polygon, strURL:String):void   {    querytaskFeaturesByPolygon.url = strURL;        queryFeaturesByPolygon.geometry = poly;        querytaskFeaturesByPolygon.execute(queryFeaturesByPolygon);   }                  protected function querytaskFeaturesByPolygon_executeCompleteHandler(event:QueryEvent):void    {          // highlight the selected features - NOT DONE     var fs:FeatureSet = event.featureSet;          var attributes:Array = fs.attributes;     var al:ArrayList = new ArrayList();          for each (var objRec in attributes)     {      al.addItem(objRec);     }                        //code continues....
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
IvanBespalov
Frequent Contributor
frank,
in this sample with sources used AsyncResponder, token ...

View solution in original post

0 Kudos
4 Replies
Drew
by
Frequent Contributor
I think you have to separate the complete function from the reusable code.

Consider doing something like the below sample code..
I did not test the code.. but it should help.


notice the "callBackFunction:Function" paramater... it would be your onQueryComplete function


private function FilterAttributeTablesByPolygon(poly:Polygon, strURL:String, callBackFunction:Function):void
{
 var querytaskFeaturesByPolygon:QueryTask = new QueryTask();
  querytaskFeaturesByPolygon.url = strURL;
 
 var queryFeaturesByPolygon:Query = new Query();
  queryFeaturesByPolygon.geometry = poly;
 
 querytaskFeaturesByPolygon.execute(queryFeaturesByPolygon,  new AsyncResponder(callBackFunction, faultFunction);
}

private function testquery()
{
 //FIRST CALL
 FilterAttributeTablesByPolygon(new Polygon(),"http://......", function(event:QueryEvent):void
 {
  var fs:FeatureSet = event.featureSet; 
  //......Handle results here
  
  //SECOND CALL Called once first is completed...
  FilterAttributeTablesByPolygon(new Polygon(),"http://......", function(event:QueryEvent):void
  {
   var fs2:FeatureSet = event.featureSet; 
   //......Handle results here
  });
  
 });

}



Hope that helps.

Drew
0 Kudos
MarkDeaton
Esri Contributor
Another approach might be to use the AsyncToken that comes back from the call to execute. If you grab that AsyncToken, you can add an event listener to it like this (here I'm using an HTTPService call, but it should work similarly for your Task):
var iCallId:int = 0;
var responderToken:Object = { callId : iCallId++ };
var asyncToken:AsyncToken = configService.send();
asyncToken.addResponder(new AsyncResponder(configResult, configFault, responderToken));


And you can now put your result-handling logic in a different event listener, configResult(), which will be passed the token (type Object--anything you want) you sent in right after you made the request. You can add any kind of property you want to this token, including an incremental counter or unique ID for the call.

More info:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/rpc/AsyncToken.html

Edit: Here's an example from Adobe, showing how to do the same thing in an even simpler way than I demonstrated above:
http://cookbooks.adobe.com/post_Tracking_results_from_multiple_simultaneous_servic-922.html
0 Kudos
IvanBespalov
Frequent Contributor
frank,
in this sample with sources used AsyncResponder, token ...
0 Kudos
chuckfrank
Frequent Contributor
Thanks to all of you!  I went with the solution of using an AsyncResponder with a token like this:

private function FilterAttributeTablesByPolygon(poly:Polygon, strURL:String):void
{
   
    var token:Object = new Object();

    // set the token to the URL of the feature layer to know witch feature layer is being queried when the result is returned  
    token = strURL;
    
    querytaskFeaturesByPolygon.url = strURL;
   
    queryFeaturesByPolygon.geometry = poly;

    // pass the token in the responder 
    querytaskFeaturesByPolygon.execute(queryFeaturesByPolygon, new AsyncResponder(querytaskFeaturesByPolygon_executeCompleteHandler, querytask_faultHandler, token));
   
}


Then I modified the query result function to accept and read the token:

protected function querytaskFeaturesByPolygon_executeCompleteHandler(fs:FeatureSet, token:Object = null):void
{
    
    var attributes:Array = fs.attributes;
    var al:ArrayList = new ArrayList();
    
    for each (var objRec in attributes)
    {
        al.addItem(objRec);
    }
    

    // use the token value in a switch statement   
    switch(token)
    {
     ....Code continues....



Thanks for all of your suggestions.  This is working with code that I can reuse query any featurelayer by a polygon.
0 Kudos