Skip navigation
bla124356
Currently Being Moderated

Dual EventListener problem

Sep 16, 2012 11:35 AM

Hello All,

 

I am new to these forums, and to ActionScript. I have come here to ask the following question, as I cannot find answers elsewhere.

 

I have the following short piece of as3 script:

 

import flash.display.Bitmap;

import flash.display.Loader;

import flash.events.Event;

import flash.net.URLLoader;

import flash.net.URLRequest;

 

var imageArray:Array = new Array();

var file:String = "xml/images.xml";

 

var loader:URLLoader = new URLLoader();

var request:URLRequest = new URLRequest(file);

loader.load(request);

loader.addEventListener(Event.COMPLETE, xmlReady);

 

function xmlReady(e:Event):void {

     var xmlData = XML(e.target.data);

     trace(xmlData);

     loadImages(xmlData);

     addEventListener(Event., traceArray);

}

 

function loadImages(images:XML):void {

     for (var i:Number = 0; i < images.length(); i++){

     var loader:Loader = new Loader();

     var request:URLRequest = new URLRequest(images.node[i].@f); // load element f (filepath/filename.jpg) out of a node element

     loader.load(request);

     loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageReady);

     }

}

 

function imageReady(e:Event):void {

     imageArray.push(e.target.content as Bitmap);

}

 

function traceArray():void{

     trace(imageArray.length);

}

 

The script does not throw any exceptions or warnings. Somehow, the script will only load one image into array imageArray, in stead of all (5) images specified in the XML document. I am certain that the XML is correct, because the XML object can load it's data and display it (i tested this). I suspect this problem has something to do with the asynchronous execution due to COMPLETE events being used. Can anyone point me in the right direction as to how this script may be rewritten in a better (functional) way and/or tell me a way to do load assets in as3 without using events? Or is this the only way possible in as3 in order to prevent browser freezes?

 

With regards,

 

bla124356

 
Replies
  • Currently Being Moderated
    Sep 16, 2012 11:59 AM   in reply to bla124356

    1. What event are listening to in the line addEventListener(Event., traceArray);?

     

    2. What do you see in traces:

     

     

    function loadImages(images:XML):void
    {
        for (var i:Number = 0; i < images.length(); i++)
        {
            trace(images.node[i].@f);
            var loader:Loader = new Loader();
            var request:URLRequest = new URLRequest(images.node[i].@f); // load element f (filepath/filename.jpg) out of a node element
            loader.load(request);
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageReady);
            
        }
     
    }
    

     

    3. All listeners MUST BE ADDED BEFORE load is called. In local environments it is so fast that load may be complete before Flash hears the event listener to which is added.

     

    So you code should be something like this

     

     

    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.events.Event;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
     
    var imageArray:Array = new Array();
    var file:String = "xml/images.xml";
    var loader:URLLoader = new URLLoader();
    var request:URLRequest = new URLRequest(file);
    loader.addEventListener(Event.COMPLETE, xmlReady);
    loader.load(request);
     
     
    function xmlReady(e:Event):void
    {
        var xmlData = XML(e.target.data);
        trace(xmlData);
        addEventListener(Event.ENTER_FRAME, traceArray);
        loadImages(xmlData);
        
    }
     
    function loadImages(images:XML):void
    {
        var loader:Loader;
        for (var i:int = 0; i < images.length(); i++)
        {
            trace(images.node[i].@f);
            loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageReady);
            loader.load(new URLRequest(images.node[i].@f));
        }
     
    }
     
    function imageReady(e:Event):void
    {
        imageArray.push(e.target.content as Bitmap);
        LoaderInfo(e.target).removeEventListener(Event.COMPLETE, imageReady);
    }
     
    function traceArray():void
    {
        trace(imageArray.length);
    }
    
     
    |
    Mark as:
  • Currently Being Moderated
    Sep 16, 2012 12:11 PM   in reply to bla124356

    In you original code there is no Event type specified when you add event listener in xmlReady() function.

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 16, 2012 12:18 PM   in reply to bla124356

    What do you see in traces output in this funcion?

     

    function loadImages(images:XML):void

    {

        for (var i:int = 0; i < images.length(); i++)

        {

            trace(images.node[i].@f);

            var loader:Loader = new Loader();

            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageReady);

            loader.load(new URLRequest(images.node[i].@f));

        }

    }

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 16, 2012 1:03 PM   in reply to bla124356

    You don't read nodes properly.

     

    Loop must be:

     

    for (var i:int = 0; i < images.node.length(); i++)

     

    not

     

    for (var i:int = 0; i < images.length(); i++)

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 16, 2012 1:09 PM   in reply to bla124356

    You don't have to use for loop. Use for...each loop - it is faster:

     

     

    function loadImages(images:XML):void
    {
        var loader:Loader;
        for each (var node:XML in images.node)
        {
            trace(node.@f);
            loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageReady);
            loader.load(new URLRequest(node.@f));
        }
    }
    
     
    |
    Mark as:
  • Currently Being Moderated
    Sep 17, 2012 4:41 AM   in reply to bla124356

    I think it should be mentioned you could've, and probably should've, been using an XMLList object - it is what has the length() method and makes iterating chunks of XML easy.

     

    So, in your xmlReady function:

     

    function xmlReady(e:Event):void {

              var xmlData:XML = new XML(e.target.data);

              trace(xmlData);

     

              var nodeList:XMLList = xmlData.node;

              trace(nodeList.length()); //5

              trace(nodeList[0].@f); //images/1.jpg

    }

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points