0

i'm having some issues with AS3. Pulling an array successfully from XML, but outside of the function there is no "saved" array. Tracing the array inside the function works fine.

If somebody could lend a hand that'd be great- thanks!

Merry Christmas!

AS3

var mapLocations:Array = new Array();

var xmlLoader:URLLoader = new URLLoader();
xmlLoader.addEventListener(Event.COMPLETE, showXML);
xmlLoader.load(new URLRequest("mapLocations.xml"));
function showXML(e:Event){
    XML.ignoreWhitespace = true; 
    var xml:XML = new XML(e.target.data);
    for (i=0; i<xml.loc.length(); i++) {
        mapLocations.push([
                       xml[0].loc[i].locname,
                       xml[0].loc[i].locx,
                       xml[0].loc[i].locy
                     ]);
    }
    trace(mapLocations); // NOT BEING RETURNED OUTSIDE FUNCTION!
}
1
  • Could you post an example? I'm a little unsure of what you mean. Commented Dec 24, 2012 at 18:46

3 Answers 3

1

The code is executed asynchronously. When u trace the array outside of the callback - the timeline's scope - the array has not been updated with the loaded XML data. You HAVE to implement a control flow using methods, which call each other. Statements in the timeline code is executed synchronously after start up.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, that makes sense! I'll write a callback in.
It makes sense, but it's only halfway good advice. The point is well-taken that you're reading the variable before it has been written (it's not a scope, but a timing issue). However, you can't force asynchronous code to be synchronous. One way you can handle this instead is to dispatch an "xmlReadDone" variable in the event handler, listen for that, and trace the value of your variable then. What's the ultimate goal you're hoping to accomplish.
I never pointed out that it was a scope problem, just that you can't simply read the data at any point of the timeline's scope. And there is no need to dispatch a new event. There has just a new method to be called which gets the loaded data passed. It manipulates the data, loads new stuff, sets event listeners or whatever. The key is to understand that parts of the application need to be handled asynchronously, while others don't.
1

Since you asked for example:

package examples
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLLoader;
    import flash.net.URLRequest;

    public class XMLLoadingExample extends Sprite
    {
        public function XMLLoadingExample()
        {
            super();
            loadLocations();
        }

        private function loadLocations():void
        {
            var xmlLoader:URLLoader = new URLLoader();
            xmlLoader.addEventListener(
                Event.COMPLETE, locationsLoadHandler);
            xmlLoader.load(new URLRequest("mapLocations.xml"));
        }

        // This code handles the initial reception of XML
        // and passes it further for more processing
        private function locationsLoadHandler(event:Event):void
        {
            XML.ignoreWhitespace = true; 
            var xml:XML = XML(event.target.data);
            var result:Array = [];
            for each (var node:XML in xml.loc)
                result.push(node.locname, node.locx, node.locy);
            // Call some other code that waits for the
            // results of loading this XML file
            handleMapLocations(result);
        }

        private function handleMapLocations(locations:Array):void
        {
            // Do whatever you wanted with your location data here
        }
    }
}

Comments

0

I think you have a problem with XML. Code is OK.

Try this XML:

<root>
    <loc>
        <locname>object 1</locname>
        <locx>10</locx>
        <locy>100</locy>
    </loc>
    <loc>
        <locname>object 2</locname>
        <locx>20</locx>
        <locy>200</locy>
    </loc>
    <loc>
        <locname>object 3</locname>
        <locx>30</locx>
        <locy>300</locy>
    </loc>
</root>

You can also try with this XML:

<root>
    <loc name="object 1" x="10" y="100" />
    <loc name="object 2" x="20" y="200" />
    <loc name="object 3" x="30" y="300" />
</root>

and the modified code:

...
mapLocations.push([
    xml[0].loc[i].@name,
    xml[0].loc[i].@x,
    xml[0].loc[i].@y
]);
...

2 Comments

Merry Christmas to you too :)
Nice solutions, but there's no issue with the XML. The trace code works within the function fine- it picks up the data okay; I could assume as the below answer that it's a timing issue in the fact that it's not in a callback. Thanks anyway :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.