如何从actionscript事件中返回变量?加载XML文件

时间:2013-03-03 12:04:03

标签: actionscript-3 flex

我正在尝试从我的资源文件夹中加载xml文件。

我写了这个函数:

        public static function loadXML(i_fileURL:String):XML // i want to return the actual loaded xml here
    {
        var xml:XML;
        var ldr:URLLoader = new URLLoader();
        var request:URLRequest = new URLRequest(i_fileURL);
         ldr.addEventListener(Event.COMPLETE, onXMLLoad);
         ldr.load(request);
                     //how can i return the loaded xml?
    }

        public static function onXMLLoad(e:Event):void
    {
        var ldr:URLLoader = URLLoader(e.target);
        var myxml:XML = new XML(ldr.data);
        trace(myxml.toXMLString());
                   //how can i return myxml to loadXML function?

    }

有不同的方法吗?

谢谢!

3 个答案:

答案 0 :(得分:1)

您可以执行类似承诺或未来的操作,返回空XML,然后在调用返回时使用实际XML填充它。由于您使用的是Flex,因此您可以访问数据绑定,这应该允许这种方法正常工作。

请注意,您确实不应该使用静态方法,并且您的onXMLLoad成员没有理由被公开。以下是更新后的代码:

package service {
    public class XMLLoader {
        //note that the existence of this variable means that you need
        //to create a new instance of the Class each time you make a call.
        protected var future:XML;
        protected var _url:String;
        public function loadXML(url:String):XML {
            _url = url;
            var request:URLRequest = new URLRequest(url);
            var loader:URLLoader = new URLLoader();
            loader.addEventListener(Event.Complete, onLoad);
            loader.addEventListener(IoErrorEvent.IO_Error, onFail);
            loader.addEventListener(SecurityErrorEvent.Security_Error, onFail);
            future = ;
            return future;
        }
        protected function onLoad(e:Event):void {
            var loader:URLLoader = e.currentTarget as URLLoader;
            var data:XML = loader.data as XML;
            if (data) {
               //you lose your original root node, because you want data
               //binding to fire on the future object you returned.
               future.setChildren(data.children());
            }
        }
        protected function onFail(e:Event):void {
            //both Security and IOerrors have a text property, but they
            //can't both be cast to the same thing.
            trace('failed to load', _url, e[text]);
        }
    }
}

使用此方法需要注意的一件事是,您需要在数据更新之前保留对实例的引用,否则可能在填充未来之前对其进行垃圾回收。因此,您可能最好遵循传统的方法,让您的实例调度一个自定义事件,该事件包含它正在检索的数据。如果您想要一个例子,请回复,我可以为您提供一个示例。

答案 1 :(得分:0)

你不能。因为xml加载请求是异步的。当您致电loadXML时,onXMLLoad尚未到达。所以这种工作不可能异步返回。当然你可以等待函数进程while循环使用,但这种方法并不好。因为要充分利用cpu资源,矫枉过正。你必须在onXMLLoad函数中进行下一步处理。这是最合适的。或声明为全局的xml变量,并使用ENTER_FRAMETimerEvent作为在xml不为空时继续操作的方法。

答案 2 :(得分:0)

由于URLLoader是异步的,因此创建静态加载器函数并不安全,因为在多次调用期间很容易混淆返回的数据。即使您尝试使用Event.OPEN和URL向量来跟踪每个URL应该属于哪些已完成的数据,也可以按照先到先得的原则进行操作不可能持久对齐文件URL和返回的数据。

我建议您创建使用自定义XMLLoader的{​​{1}}类的实例,该类将返回xml数据和关联的文件URL。以下代码未经测试,但除了可能的拼写错误之外,它应该按预期工作。

使用案例

XMLLoaderEvent

<强> XMLLoader.as

var xmlLoader:XMLLoader = new XMLLoader();
xmlLoader.addEventListener(XMLLoaderEvent.COMPLETE, xmlLoadCompleteEventHandler);
xmlLoader.load("myXMLFile.xml");

function xmlLoadCompleteEventHandler(event:XMLLoaderEvent):void
{
    xmlLoader.removeEventListener(XMLLoaderEvent.COMPLETE, xmlLoadCompleteEventHandler);

    trace(event.type, event.fileURL, event.xml);
}

<强> XMLLoaderEvent.as

package
{
    //Imports
    import flash.events.EventDispatcher;
    import flash.events.Event;
    import flash.net.URLLoader;
    import flash.net.URLRequest;

    //Class
    public class XMLLoader extends EventDispatcher
    {
        //Properties
        private var loader:URLLoader;
        private var fileURL:String;

        //Constructor
        public function XMLLoader():void
        {
            loader = new URLLoader();
            loader.addEventListener(Event.COMPLETE, loadCompleteEventHandler);
        }

        //Load
        public function load(fileURL:String):void
        {
            this.fileURL = fileURL;

            loader.load(new URLRequest(fileURL));            
        }

        //Load Complete Event Hanlder
        private function loadCompleteEventHandler(event:Event):void
        {
            loader.removeEventListener(Event.COMPLETE, loadCompleteEventHandler);

            dispatchEvent(new XMLLoaderEvent(XMLLoaderEvent.COMPLETE, fileURL, XML(loader.data)));
        }
    }
}