• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Dual EventListener problem

New Here ,
Sep 16, 2012 Sep 16, 2012

Copy link to clipboard

Copied

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.@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

TOPICS
ActionScript

Views

2.1K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Sep 16, 2012 Sep 16, 2012

Copy link to clipboard

Copied

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.@f);

        var loader:Loader = new Loader();

        var request:URLRequest = new URLRequest(images.node.@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.@f);

        loader = new Loader();

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

        loader.load(new URLRequest(images.node.@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);

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 16, 2012 Sep 16, 2012

Copy link to clipboard

Copied

Ahh that explains a lot, thanks! Well my final trace(imageArray.length); in the traceArray eventlistener is to check if in the end, my array contains any elements. But it doesn't return anything, which is why I am here The trace(images.node.@f); is to display the current file being loaded into the array.

I will give this a shot and report back!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Sep 16, 2012 Sep 16, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 16, 2012 Sep 16, 2012

Copy link to clipboard

Copied

I have changed the source to:

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.addEventListener(Event.COMPLETE, xmlReady);

loader.load(request);

function xmlReady(e:Event):void {

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

          trace(xmlData);

          loadImages(xmlData);

}

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.@f);

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

                    loader.load(request);

          }

}

function imageReady(e:Event):void {

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

          trace(imageArray.length);

}

Now, I have come to suspect that the for loop does not play nice with events. I will research whether a solution in which each eventhandler loading an image from xml handles iteration using a global instead of using a for loop and see if that works.

P.S. how put my source in a nice code box here on the forums?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Sep 16, 2012 Sep 16, 2012

Copy link to clipboard

Copied

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.@f);

        var loader:Loader = new Loader();

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

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

    }

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 16, 2012 Sep 16, 2012

Copy link to clipboard

Copied

I did not see the trace in that function.

I have changed my code to:

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 arrayLength:Number = 0;

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);

          trace(xmlData.node.length);

          trace(xmlData.length);

          arrayLength = xmlData.node.length;

          loadImages(xmlData);

}

function loadImages(images:XML):void {

          while (arrayLength > 0){

                    var loader:Loader = new Loader();

                    var request:URLRequest = new URLRequest(images.node[arrayLength].@f);

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

                    loader.load(request);

          }

}

function imageReady(e:Event):void {

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

          arrayLength--;

          trace(imageArray.length);

}

And here is the output:

<root>

  <node id="1" f="images/1.jpg" th="images/thumbs/1.jpg" t="image 1"/>

  <node id="2" f="images/2.jpg" th="images/thumbs/2.jpg" t="image 2"/>

  <node id="3" f="images/3.jpg" th="images/thumbs/3.jpg" t="image 3"/>

  <node id="4" f="images/4.jpg" th="images/thumbs/4.jpg" t="image 4"/>

  <node id="5" f="images/5.jpg" th="images/thumbs/5.jpg" t="image 5"/>

</root>

Now, it seems that for some weird reason, the xmlData in the xmlReady event handler is having a fit of quantum weirdness. As you can see, trace(xmlData); works and output's it's xml. However, trace(xmlData.node.length); and trace(xmlData.length); do not work. Any ideas?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Sep 16, 2012 Sep 16, 2012

Copy link to clipboard

Copied

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++)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 18, 2012 Sep 18, 2012

Copy link to clipboard

Copied

Thanks! I seem to have looked over that one!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Sep 16, 2012 Sep 16, 2012

Copy link to clipboard

Copied

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));

    }

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 18, 2012 Sep 18, 2012

Copy link to clipboard

Copied

Thanks! I'll keep that in mind!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Sep 17, 2012 Sep 17, 2012

Copy link to clipboard

Copied

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

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 18, 2012 Sep 18, 2012

Copy link to clipboard

Copied

LATEST

Well the XML object should provide the same functionality (i tested it and it does) but, perhaps this is good practice. Thanks!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines