0

我正在尝试从我的资产文件夹中加载一个 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?

    }

有不同的方法可以做到这一点吗?

谢谢!

4

3 回答 3

1

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

请注意,您确实不应该为此使用静态方法,并且您的 onXMLLoad 成员没有理由暴露。更新后的代码可能如下所示:

包服务{
    公共类 XMLLoader {
        //注意这个变量的存在意味着你需要
        //每次调用时创建一个新的类实例。
        受保护的 var 未来:XML;
        受保护的var _url:字符串;
        公共函数 loadXML(url:String):XML {
            _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);
            未来 = ;
            返回未来;
        }
        受保护的函数 onLoad(e:Event):void {
            var loader:URLLoader = e.currentTarget as URLLoader;
            var data:XML = loader.data 作为 XML;
            如果(数据){
               //你失去了原来的根节点,因为你想要数据
               //绑定以触发您返回的未来对象。
               未来.setChildren(data.children());
            }
        }
        受保护的功能 onFail(e:Event):void {
            //Security 和 IOerrors 都有一个 text 属性,但是它们
            //不能都被转换成同一个东西。
            trace('加载失败', _url, e[text]);
        }
    }
}

使用此方法需要注意的一件事是,您需要保留对实例的引用,直到数据更新,否则它可能会在填充未来之前被垃圾收集。因此,您最好遵循让您的实例分派一个自定义事件来承载它正在检索的数据的传统方法。如果您想要一个示例,请回帖,我可以为您提供一个示例。

于 2013-03-03T19:27:48.173 回答
0

由于 URLLoader 是异步的,因此创建静态加载器函数并不安全,因为在多次调用期间很容易混淆返回的数据。即使您尝试使用Event.OPEN和一个 URL 向量来跟踪哪些已完成的数据应属于每个 URL 来完成您想要的操作,异步也以先到先得的方式工作,因此不会可以使文件 URL 和返回的数据保持一致。

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

用例

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

XMLLoader.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)));
        }
    }
}

XMLLoaderEvent.as

package
{
    //Imports
    import flash.events.Event;

    //Class
    public class XMLLoaderEvent extends Event
    {
        //Constants
        public static const COMPLETE:String = "complete";

        //Properties
        public var xml:XML;
        public var fileURL:String;

        //Constructor
        public function XMLLoaderEvent(type:String, fileURL:String = null, xml:XML = null) 
        {
            super(type);

            this.xml = xml;
            this.fileURL = fileURL;
        }

        //Clone
        public override function clone():Event
        {
            return new XMLLoaderEvent(type, fileURL, xml);
        }

        //To String
        public override function toString():String
        {
            return formatToString("XMLLoaderEvent", "type", "fileURL", "xml");
        }
    }
}
于 2013-03-04T01:30:09.287 回答
0

你不能。因为xml加载请求是异步的。你打电话的时候loadXMLonXMLLoad还没到。所以这样的工作不可能异步返回。当然你可以等待函数处理while循环使用,但这种方法不好。因为要充分利用cpu资源,大材小用。您必须在onXMLLoad功能中进行下一步处理。这是最合适的。or xml 变量声明为全局变量,如果 xml 不为 null,则使用ENTER_FRAMEorTimerEvent作为继续操作的方式。

于 2013-03-03T12:25:23.073 回答