2013-03-03 67 views
0

我想從我的資產文件夾加載一個XML文件。如何從一個動作事件返回一個變量?加載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? 

    } 

是否有不同的方式來做到這一點?

謝謝!

回答

0

你不行。因爲xml加載請求是異步的。當您撥打loadXML時,onXMLLoad尚未到達。所以這種工作不可能異步返回。當然你可以等待函數進程while循環使用,但是這種方法不好。因爲要充分利用cpu資源,矯枉過正。您必須在onXMLLoad函數中進行下一個處理。這是最合適的。或聲明爲全局的xml變量,如果xml不爲空,則使用ENTER_FRAMETimerEvent作爲繼續操作的方式。

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

有一點要注意的這種方法是,你需要一個參考保持到實例四周,直至數據已更新,否則可能被垃圾收集在它填補未來之前。因此,您可能最好遵循傳統的方法,讓您的實例分派一個自定義事件,並攜帶正在檢索的數據。如果你想要一個例子,請回過頭,我可以給你一個例子。

0

由於URLLoader是異步的,所以創建一個靜態加載函數並不安全,因爲在多次調用期間它很容易混合返回的數據。即使您試圖通過使用Event.OPEN以及一個URL向量來完成您想要的操作,以跟蹤哪些完成的數據應該屬於每個URL,但異步按照先到先得的原則工作,因此它不會可以持久地對齊文件URL和返回的數據。

我建議您創建XMLLoader類的實例,該類使用自定義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"); 
     } 
    } 
} 
相關問題