Actionscript 3 - How to keep the value from an event after removing that event

南楼画角 提交于 2021-02-19 08:14:06

问题


I set a value to my xml object (xml = new XML(e.currentTarget.data);) during my event handler function (the function is executed after the event.COMPLETE) and if I trace the object inside my event function handler it shows my xml data.

but if I try to trace it outside the event handler function it doesn't show my xml content. Isn't there a way to get my xml object content value to show in an other function but not in the event handler function?

private var xml:XML; 

public function XMLLoader(xmlURL:String) 
{ 
    var xmlURLRequest:URLRequest = new URLRequest(xmlURL); 
    var xmlURLLoader:URLLoader  = new URLLoader(xmlURLRequest); 
    xmlURLLoader.addEventListener(Event.COMPLETE, xmlData); 
}

private function xmlData(e:Event):void 
{
    e.currentTarget.removeEventListener(Event.COMPLETE, xmlData); 
    xml = new XML(e.currentTarget.data); 
    dispatchEvent(new Event(Event.COMPLETE)); 
    trace(xml); 
} 

public function getXMLData():void 
{ 
     //I've find out that this shows null because this function is faster
     //what do i do? put an event.complete in every following function?
    trace(xml);
}

Thanks.


回答1:


I think you call getXMLData() immediatelly after XMLLoader() at that moment xml object is still null. Try calling getXMLData() inside xmlData() function and you should see the difference.




回答2:


You are probably calling getXMLData() before your URLLoader completes however, in general, the code you are executing is in bad practice. Actionscript has no blocking whatsoever, so when you instantiate your new URLLoader with your URLRequest, it immediately begins the loading operation. If your file is cached, for example, your Event.COMPLETE listener may never fire as you are attaching it after you begin your loading operation.

I've attached below the ideal process for creating and loading data:

var data:XML;
var urlLoader:URLLoader = new URLLoader();

urlLoader.addEventListener(Event.COMPLETE, urlLoader_completeHandler);
urlLoader.load(new URLRequest("path"));

private function urlLoader_completeHandler(event:Event):void
{
    data = new XML(urlLoader.data);
}

If you want to apply this to your own XMLLoader class, I've included the "proper" implementation in AS3...however quite verbose.

import flash.net.URLLoader;
import flash.events.Event;

class XMLLoader extends URLLoader
{
    public function XMLLoader()
    {
        super();
        addEventListener(Event.COMPLETE, completeHandler);
    }

    private function completeHandler(event:Event):void
    {
        dispatchEvent(new XMLLoaderEvent(XMLLoaderEvent.COMPLETE, new XML(data)));
    }
}

class XMLLoaderEvent extends Event
{
    public static const COMPLETE:String = "xmlLoaderComplete";

    public var data:XML;

    public function XMLLoaderEvent(type:String, data:XML = null, bubbles:Boolean = false, cancelable:Boolean = false)
    {
        super(type, bubbles, cancelable);

        this.data = data;
    }

    override public function clone():Event
    {
        return new XMLLoaderEvent(type, data, bubbles, cancelable);
    }
}

To use the XMLLoader class:

var xmlLoader:XMLLoader = new XMLLoader();
xmlLoader.addEventListener(XMLLoaderEvent.COMPLETE, function(event:XMLLoaderEvent):void
{
    trace(event.data);
});

xmlLoader.load(new URLRequest("data.xml"));

Best of luck!




回答3:


change your trace method to indicate if the xml is loaded yet...
you are running into a race condition

private var _xmlLoaded:Boolean=false;// add this to see if the xml is loaded
private function xmlData(e:Event):void 
{
    e.currentTarget.removeEventListener(Event.COMPLETE, xmlData); 
    xml = new XML(e.currentTarget.data); 
    _xmlLoaded=true;
    dispatchEvent(new Event(Event.COMPLETE)); 
    trace(xml); 
} 
public function getXMLData():void 
{ 
    if (_xmlLoaded)
        trace(xml);
    else
        trace("not yet loaded");
}



回答4:


//NOTE: USE THIS IF YOU WANT TO ACCESS DIRECTLY TO THE FUNCTIONS OF THIS "CLASS" WITHOUT USING ANY EVENT LISTENER ON THE CLASS CAUSE IT ALREADY HAS ITS EVENT LISTENER ON EACH FUNCTION (THIS CAUSE ONE FUNCTION ONLY getXMLData())

private var xml:XML;

public function XMLLoader(xmlURL:String) {

     var xmlURLRequest:URLRequest = new URLRequest(xmlURL); 
     var xmlURLLoader:URLLoader  = new URLLoader(xmlURLRequest); 
     xmlURLLoader.addEventListener(Event.COMPLETE, xmlData); 

}

private function xmlData(e:Event):void {

     e.currentTarget.removeEventListener(Event.COMPLETE, xmlData); 
     xml = new XML(e.currentTarget.data); 
     dispatchEvent(new Event(Event.COMPLETE)); 
     trace("1");//this used to come second of getXMLData() but it's solved now
     trace(xml); 

}

public function getXMLData():void {

     //This function was coming first so if you don't want to use an event listener outside    
     //this class to wait for event.complete you can use it here to wait for it and access
     //the function directly without being afraid of the object being null:
     addEventListener(Event.COMPLETE, go)
     function go(e:Event){
          trace("2"); //now it ONLY comes AFTER the event.complete, no need for external                   listeners over this class. declare the class object and use getXMLData() directly cause it always comes second the event handler xmlData() :)
          trace(xml);
     }
}


来源:https://stackoverflow.com/questions/8378027/actionscript-3-how-to-keep-the-value-from-an-event-after-removing-that-event

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!