我创建了一个AS类用作数据模型,如下所示:
package
{
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
public class Model
{
private var xmlService:HTTPService;
private var _xml:XML;
private var xmlChanged:Boolean = false;
public function Model()
{
}
public function loadXML(url:String):void
{
xmlService = new HTTPService();
if (!url)
xmlService.url = "DATAPOINTS.xml";
else
xmlService.url = url;
xmlService.resultFormat = "e4x";
xmlService.addEventListener(ResultEvent.RESULT, setXML);
xmlService.addEventListener(FaultEvent.FAULT, faultXML);
xmlService.send();
}
private function setXML(event:ResultEvent):void
{
xmlChanged = true;
this._xml = event.result as XML;
}
private function faultXML(event:FaultEvent):void
{
Alert.show("RAF data could not be loaded.");
}
public function get xml():XML
{
return _xml;
}
}
}
在我的主应用程序中,我正在启动应用程序并调用loadXML函数来获取XML:
<fx:Script>
<![CDATA[
import mx.containers.Form;
import mx.containers.FormItem;
import mx.containers.VBox;
import mx.controls.Alert;
import mx.controls.Button;
import mx.controls.Label;
import mx.controls.Text;
import mx.controls.TextInput;
import spark.components.NavigatorContent;
private function init():void
{
var model:Model = new Model();
model.loadXML(null);
//the following line executes before model.loadXML has finished...
var xml:XML = model.xml;
}
]]>
</fx:Script>
我遇到的麻烦是getter函数在loadXML完成之前运行,因此我的主应用程序中的XML varible在堆栈跟踪中未定义。具体来说,loadXML函数调用ResultEvent.RESULT,然后跳转到setXML等...主应用程序中的代码继续执行而loadXML等待结果,因此主应用程序中的getter(var xml:XML = model。 xml;)在setXML定义变量之前执行。
如何在这里放置条件告诉getter等到loadXML()函数在运行之前完成?
答案 0 :(得分:1)
这应该像我在评论中所说的那样使用
异步完成令牌设计模式 Flex / AS不进行同步调用。
public function loadXML(url:String):void
{
xmlService = new HTTPService();
if (!url)
xmlService.url = "DATAPOINTS.xml";
else
xmlService.url = url;
xmlService.resultFormat = "e4x";
xmlService.addEventListener(ResultEvent.RESULT, setXML);
xmlService.addEventListener(FaultEvent.FAULT, faultXML);
var xmlCall:Object = xmlService.send();
xmlCall.name = "SET";
}
private function setXML(event:ResultEvent):void
{
var xmlCall:Object = event.token; // Asynchronous Completion Token
if(xmlCall.name == "SET"){
xmlChanged = true;
this._xml = event.result as XML;
}
else {
// not ready to set
}
}
您可以阅读设计模式here。
答案 1 :(得分:0)
这可能只是你在这里粘贴的印刷错误
private function setXML(event:ResultEvent):void
缺少一个空格,制作一个setXML函数而不是settign一个XML变量......这会导致你的问题吗?
答案 2 :(得分:0)
这将按设计工作。由于xml服务是异步请求,因此它会关闭请求,然后继续评估步骤。在这种情况下继续调用getter方法。
所以要注意的主要是你不能直接设置xml。返回结果后,必须设置xml对象。您可以通过向模型添加事件侦听器来执行此操作,以便在返回服务后,也会通知主程序包,或者通过绑定主程序包和模型xml之间的xml值。
答案 3 :(得分:0)
您的模型应该扩展EventDispatcher并且(使用自定义事件)调度一个事件,指示模型已成功加载。这是必需的,因为Flex是异步...
然后在创建模型后的应用程序中,只需将事件监听器添加到load事件,然后在那里可以开始使用模型变量
不要忘记发送和收听任何错误事件!
HTH 格斯
像这样......
主app中的:
var model:Model = new Model();
// registering the listener
model.addEventListener(ModelEvent.LOADED, model_loadedHandler);
model.loadXML(null);
然后是听众
private function model_loadedHandler (event:ModelEvent):void
{
var xml:XML = model.xml;
}
最后,在模型中:
private function setXML(event:ResultEvent):void
{
xmlChanged = true;
this._xml = event.result as XML;
var modelEvent:ModelEvent = new ModelEvent(ModelEvent.LOADED);
// you can add other info to the event like the XML
dispatch(modelEvent);
}
答案 4 :(得分:0)
感谢您对此提供的所有帮助,特别是Gus为我提供了很棒的代码和链接。这是我用来执行此操作的最终代码:
主要应用:
<fx:Script>
<![CDATA[
import flash.events.Event;
import mx.containers.Form;
import mx.containers.FormItem;
import mx.containers.VBox;
import mx.controls.Alert;
import mx.controls.Button;
import mx.controls.Label;
import mx.controls.Text;
import mx.controls.TextInput;
import spark.components.NavigatorContent;
private var model:Model = new Model();
private function init():void
{
model.addEventListener(Event.COMPLETE, model_loadedHandler);
model.loadXML(null);
}
private function model_loadedHandler (e:Event):void
{
var xml:XML = model.xml;
var sectorList:XMLList = xml.SECTOR;
trace(sectorList);
}
}
]]>
</fx:Script>
和Model.as:
package
{
import flash.events.Event;
import flash.events.EventDispatcher;
import mx.controls.Alert;
import mx.rpc.AsyncToken;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
public class Model extends EventDispatcher
{
private var xmlService:HTTPService;
private var _xml:XML;
public function loadXML(url:String):void
{
xmlService = new HTTPService();
if (!url)
xmlService.url = "DATAPOINTS.xml";
else
xmlService.url = url;
xmlService.resultFormat = "e4x";
xmlService.addEventListener(ResultEvent.RESULT, setXML);
xmlService.addEventListener(FaultEvent.FAULT, faultXML);
xmlService.send();
}
private function setXML(event:ResultEvent):void
{
this._xml = event.result as XML;
var modelEvent:Event = new Event(Event.COMPLETE);
//var modelEvent:ModelEvent = new ModelEvent(ModelEvent.LOADED);
dispatchEvent(modelEvent);
//this._xml = event.result as XML;
}
private function faultXML(event:FaultEvent):void
{
Alert.show("RAF data could not be loaded.");
}
public function get xml():XML
{
return _xml;
}
}
}
我最终使用了一个标准的事件类(我想,不完全确定为什么会这样做),现在代码运行得很好。对此有任何进一步的想法将不胜感激,但它正在运行!