Select to view content in your preferred language

return value after querytask has completed

1212
7
01-20-2012 12:39 PM
eddiequinlan
Deactivated User
Hi,

I think I'm overlooking something very simple.

1.    I'm running a QueryTask in ActionScript.
2.    When it's complete, I want the returned value stored in a variable.

When I run the code the first iteration the "trace" show 0.  The next time it shows a value, which should have been the previous value... so on and so forth.





Here's the part of the code with the issue:

sQueryTask.addEventListener(QueryEvent.EXECUTE_COMPLETE, test);
sQueryTask.execute(sQuery);

trace(nsum);       ///     Problem is here..... first query is "0", second query is the correct value from the first query..... so on and so forth.

private function test(event:QueryEvent):void
{
         nsum = 0;
         var farray:Array = event.featureSet.features;
for each (var g:Graphic in farray)
{
  nsum = nsum + g.attributes.SAPRICE;
}
// all ok here;;;       Sums all of the Sales  Prices correctly
             trace(nsum);
}

The nsum variable is being set before my QueryTask has completed and returned the correct value.  uuuuggggggghhhhhhhh

Thank you in advance,
Eddie
Tags (2)
0 Kudos
7 Replies
KenBuja
MVP Esteemed Contributor
The code is running correctly. After the program executes the querytask, it will continue through the rest of the function without waiting for the querytask results to be returned. That will happen only in your "test" function when the listener determines the execution is completed. If you want to do things with "nsum", you'll have to put that code into your "test" function. Take a look in the Query Task samples, like this, as an example.
0 Kudos
RobertScheitlin__GISP
MVP Emeritus
Eddie,

   Taking the same sample that Ken mentioned here is a quick demo:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               xmlns:esri="http://www.esri.com/2008/ags"
               pageTitle="Eddie Test">
    
    <s:layout>
        <s:VerticalLayout paddingTop="0" gap="0"/>
    </s:layout>
    
    <fx:Script>
        <![CDATA[
            import com.esri.ags.FeatureSet;
            import com.esri.ags.Graphic;
            import com.esri.ags.events.MapEvent;
            import com.esri.ags.tasks.QueryTask;
            import com.esri.ags.tasks.supportClasses.Query;
            
            import mx.collections.ArrayCollection;
            import mx.controls.Alert;
            import mx.events.FlexEvent;
            import mx.rpc.AsyncResponder;
            
            [Bindable]
            private var nsum:Number = 0;
            
            protected function button1_clickHandler(event:MouseEvent):void
            {
                var queryTask:QueryTask = new QueryTask();
                queryTask.url = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/0";
                queryTask.useAMF = false;
                var query:Query = new Query();
                query.outSpatialReference = myMap.spatialReference;
                query.outFields = [ "CITY_NAME", "AGE_UNDER5", "AGE_5_17", "AGE_18_64", "AGE_65_UP" ];
                query.returnGeometry = false;
                query.where = "upper(STATE_NAME) = upper('" + ti.text + "') AND TYPE = 'city'";
                //queryTask.concurrency = "last";
                queryTask.execute(query, new AsyncResponder(onResult, onFault));
                // add the graphic on the map
                function onResult(featureSet:FeatureSet, token:Object = null):void
                {
                    nsum = 0;
                    for each (var g:Graphic in featureSet.features)
                    {
                        nsum += g.attributes.AGE_18_64; 
                    }
                    trace(nsum); 
                }
                function onFault(info:Object, token:Object = null):void
                {
                    Alert.show(info.toString());
                }
            }
            
        ]]>
    </fx:Script>
    
    <s:BorderContainer backgroundColor="0x999999" alpha="0.8" width="100%" height="30">
        <s:HGroup gap="5" verticalAlign="middle" paddingLeft="30" height="100%" width="100%">
        <s:Label fontSize="12"
                 fontWeight="bold"
                 text="State: "/>
        <s:TextInput id="ti" text="Alaska"/>
        <s:Button click="button1_clickHandler(event)" label="Search" />
        <s:Spacer width="30" />
        <s:Label fontSize="12"
                 fontWeight="bold"
                 text="Total Population in {ti.text} from the age of 18 to 64:"/>
        <s:Label fontSize="12"
                 fontWeight="bold"
                 text="{nsum}"/>
    </s:HGroup>
    </s:BorderContainer>
    
    <esri:Map id="myMap"
              openHandCursorVisible="false">
        <esri:extent>
            <esri:Extent xmin="-19385000" ymin="6655000" xmax="-13222000" ymax="13326000">
                <esri:spatialReference>
                    <esri:SpatialReference wkid="102100"/>
                </esri:spatialReference>
            </esri:Extent>
        </esri:extent>
        <esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"/>
    </esri:Map>
</s:Application>
0 Kudos
eddiequinlan
Deactivated User
Thank you both for your suggestions. I've read many of your posts over the years and they've always been helpful.

I've used this method in the past and slight variations of it, but in this case I still get the same results.

Here is what I finally decided to use:

CODE:

SearchSaleTable(PinArray); // send array to function

trace("The very last value " + nsum);



private function SearchSaleTable(tmp:ArrayCollection):Number
{[INDENT]// loops thru the pin's to search Sale table [/INDENT]
[INDENT]
cursor = tmp.createCursor();[/INDENT]
[INDENT]var t:String = new String;[/INDENT]
[INDENT]while(!cursor.afterLast)[/INDENT]
[INDENT]{ [/INDENT]
[INDENT=2]t = cursor.current.toString();[/INDENT]
[INDENT=2]var saleQueryTask:QueryTask = new QueryTask(); [/INDENT]
[INDENT=2]
saleQueryTask.url = "my url";
saleQueryTask.showBusyCursor = true;
saleQueryTask.useAMF = false;[/INDENT]
[INDENT=2]sQuery.where = "SAPROP = '" + t + "'" ;

saleQueryTask.execute(sQuery, new AsyncResponder(onResult, onFault));

function onResult(featureSet:FeatureSet, token:Object = null):Number
{[/INDENT]
[INDENT=3]nsum = 0;[/INDENT]
[INDENT=3]for each (var g:Graphic in featureSet.features)[/INDENT]
[INDENT=3]{[/INDENT]
[INDENT=4]nsum += g.attributes.SAPRICE; [/INDENT]
[INDENT=3]}[/INDENT]
[INDENT=3]trace("on Result " + nsum); // both "trace" return correct values.........[/INDENT]
[INDENT=3]
sumSaleValue = sumSaleValue + nsum;[/INDENT]
[INDENT=3]trace("The very last value " + nsum);

trace
("The very last value "
+ nsum);
trace
("on sumSale " + sumSaleValue);
[/INDENT]
[INDENT=3]return nsum;[/INDENT]
[INDENT=2]}
[/INDENT]
[INDENT=2]function onFault(info:Object, token:Object = null😞void
{[/INDENT]
[INDENT=3]Alert.show(info.toString());[/INDENT]
[INDENT=2]}
cursor.moveNext() [/INDENT]
[INDENT]} [/INDENT]
[INDENT]return sumSaleValue; or return nsum[/INDENT]
}

This code works and will set the global variable (either nsum or sumSaleValue) after the function completes. However, what still doesn't work and is confusing me is the "trace". As I have in my code above, the line after calling the function...trace("The very last value " + nsum) still displays a "0" value, even though I know this variable is set. Is there a way to show that "trace" correctly?

Thanx,
Eddie
0 Kudos
RobertScheitlin__GISP
MVP Emeritus
Eddie,

  Adding the traces you provided into the code sample I provided this is what I get in the Output searching for Alaska:

on Result 20233
The very last value 20233
The very last value 20233
on sumSale 20233
on Result 171625
The very last value 171625
The very last value 171625
on sumSale 191858
on Result 189162
The very last value 189162
The very last value 189162
on sumSale 381020

Not sure why you are having an issue.
0 Kudos
KenBuja
MVP Esteemed Contributor
If you want to get a better idea of the order in which code functions, put in breakpoints at various points. This will show you how the program is progressing.


SearchSaleTable(PinArray); // send array to function

trace("The very last value " + nsum); 



private function SearchSaleTable(tmp:ArrayCollection):Number
{[INDENT]// loops thru the pin's to search Sale table [/INDENT]
[INDENT]
cursor = tmp.createCursor();[/INDENT]
[INDENT]var t:String = new String;[/INDENT]
[INDENT]while(!cursor.afterLast)[/INDENT]
[INDENT]{ [/INDENT]
[INDENT=2]t = cursor.current.toString();[/INDENT]
[INDENT=2]var saleQueryTask:QueryTask = new QueryTask(); [/INDENT]
[INDENT=2]
saleQueryTask.url = "my url";
saleQueryTask.showBusyCursor = true;
saleQueryTask.useAMF = false;[/INDENT]
[INDENT=2]sQuery.where = "SAPROP = '" + t + "'" ;

saleQueryTask.execute(sQuery, new AsyncResponder(onResult, onFault));

function onResult(featureSet:FeatureSet, token:Object = null):Number
{[/INDENT]
[INDENT=3]nsum = 0;   <-- put breakpoint here
[/INDENT]
[INDENT=3]for each (var g:Graphic in featureSet.features)[/INDENT]
[INDENT=3]{[/INDENT]
[INDENT=4]nsum += g.attributes.SAPRICE; [/INDENT]
[INDENT=3]}[/INDENT]
[INDENT=3]trace("on Result " + nsum); // both "trace" return correct values.........[/INDENT]
[INDENT=3]
sumSaleValue = sumSaleValue + nsum;[/INDENT]
[INDENT=3]trace("The very last value " + nsum);

trace("The very last value " + nsum);
trace("on sumSale " + sumSaleValue);
[/INDENT]
[INDENT=3]return nsum;[/INDENT]
[INDENT=2]}
[/INDENT]
[INDENT=2]function onFault(info:Object, token:Object = null):void
{[/INDENT]
[INDENT=3]Alert.show(info.toString());[/INDENT]
[INDENT=2]} 
cursor.moveNext() [/INDENT]
[INDENT]} [/INDENT]
[INDENT]return sumSaleValue; or return nsum <-- put breakpoint here
[/INDENT]
} 


You see that the breakpoint on the return is hit before the breakpoint in the function.
0 Kudos
eddiequinlan
Deactivated User
Robert,

I think in your test there are two extra lines of code; which is my fault.  They apparently were copied accidentally.

trace("The very last value " + nsum);
trace("The very last value " + nsum);

So the results of these two "trace" are the results still being calculated in the loop. 

Ken,

The break points help, but it doesn't explain why the very last "trace" (after calling the function) doesn't get the proper value???



I maybe beating a dead horse trying to figure this out and I don't want to waste everyones time.  As I said the code is working, I'm just trying to figure out the "trace" issue so I won't run into this in the future.  If you want to continue to help, that would be great;  if not, I understand.

Eddie
0 Kudos
IvanBespalov
Frequent Contributor
1
From adobe reference

result:Function â?? Function that should be called when the request has completed successfully. Must have the following signature: 
public function (result:Object, token:Object = null):void;


:confused:

void - Specifies that a function cannot return any value.

// variable=reciever layer
// function getLayer(layerId:Number):Layer returns some data with type Layer
var layer:Layer = myMap.getLayer(layerId);

// no variable=reciever
// function can not return any value
layer.refresh(); // refresh():void 


so what variable=reciever gets data, when your function works function onResult(featureSet:FeatureSet, token:Object = null):Number ?

2
function SearchSaleTable works, and never pause or stop working to wait your result or fault function. you need a pencil and a piece of paper (maybe even two pieces of paper) on which you describe everything in detail the entire cycle of receiving and processing data.

So the green part of code never wait for red part of code, right?
private function SearchSaleTable(tmp:ArrayCollection):Number
{
    cursor = tmp.createCursor();
    var t:String = new String;
    while(!cursor.afterLast)
    { 
        t = cursor.current.toString();
        var saleQueryTask:QueryTask = new QueryTask(); 

        saleQueryTask.url = "my url";
        saleQueryTask.showBusyCursor = true;
        saleQueryTask.useAMF = false;
        sQuery.where = "SAPROP = '" + t + "'" ;

        saleQueryTask.execute(sQuery, new AsyncResponder(onResult, onFault));

        function onResult(featureSet:FeatureSet, token:Object = null):void
        {
            nsum = 0;
            for each (var g:Graphic in featureSet.features)
            {
                nsum += g.attributes.SAPRICE; 
            }
            trace("on Result " + nsum);

            sumSaleValue = sumSaleValue + nsum;
        }
        function onFault(info:Object, token:Object = null):void
        {
            Alert.show(info.toString());
        } 
        cursor.moveNext() 
    } 
    return sumSaleValue; 
}


Try to remove/comment all places you call trace function.
Put in other places:

private function SearchSaleTable(tmp:ArrayCollection):Number
{
trace(">>>start of SearchSaleTable()");
...
...
trace("query send")
saleQueryTask.execute(sQuery, new AsyncResponder(onResult, onFault));
...
...
function onResult(featureSet:FeatureSet, token:Object = null):void
{
    trace("result recieve");
...
...
trace(">>>end of SearchSaleTable()");
return sumSaleValue;


my be it helps.
0 Kudos