AS3:在函数外部访问变量

时间:2017-04-19 12:38:20

标签: actionscript-3

这个问题让我疯狂,我不知道我在这里失踪了什么。这是我的代码:



package  {
	
	import flash.display.*;
	import flash.text.*;
	import flash.events.*;
	import flash.net.*;
	import flash.xml.*; 
	
	public class PopUp extends Sprite {
		
		public var container:Array = new Array();

		public function PopUp() {
			
			var contentXML:XML = new XML(); 
			var XML_URL:String = "./content/content.xml"; 
			var contentXMLURL:URLRequest = new URLRequest(XML_URL); 
			var contentLoader:URLLoader = new URLLoader(contentXMLURL); 
			contentLoader.addEventListener("complete", FuncXML);
			
			function FuncXML(event:Event):void { 
				contentXML = XML(contentLoader.data);
				for each (var item in contentXML.item) {
					
					var txtbox:Sprite = new Sprite();
					txtbox.graphics.beginFill(0x444444, 0.9);
					txtbox.graphics.drawRoundRect(0, 0, 100, 100, 15, 15)
					txtbox.graphics.endFill();
					txtbox.name = "txtbox_"+item.settings.target;
					addChild(txtbox);
					container.push(txtbox);
				}
				trace(container.length); // Returns 2
			}
		trace(container.length); // Returns 0
		}

	}
	
}




此代码的最终版本应该从xml文件的内容创建文本框,但我无法从函数" FuncXML"中获取内容。我试着跟踪了。函数内部的跟踪返回正确的"容器"的长度,即2.在函数外部,跟踪返回0.你能告诉我这里有什么问题吗?

3 个答案:

答案 0 :(得分:3)

正如在其他答案中所解释的那样,您的第二条跟踪将在内部函数中的第一条跟踪之前执行。我发生了因为URLLoader不是即时的,需要一些时间来加载数据。所以你必须等到它完成工作。您可以按照本文档中的说明等待特定事件:URLLoader Adobe Help。 下面我可以建议您可能想要做的一些基本示例:

public class PopUp extends Sprite {

    public var container:Array = new Array();
    // Class constructor       
    public function PopUp() {

    }

    public function prepareAndLoad():void {
        var XML_URL:String = "./content/content.xml"; 
        var contentXMLURL:URLRequest = new URLRequest(XML_URL); 
        var contentLoader:URLLoader = new URLLoader(); 
        contentLoader.addEventListener(Event.COMPLETE, onXMLLoadComplete);
        // good practice here would be to expect errors as well:
        contentLoader.addEventListener(IOErrorEvent.IO_ERROR, onError);
        contentLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);

        contentLoader.load(contentXMLURL);
    }
    private function onError(e:ErrorEvent):void {
        trace("Error");
        // maybe you want to handle this situation somehow.
    }

    private function onXMLLoadComplete(event:Event):void { 
        var contentXML:XML = XML(event.target.data);
        for each (var item in contentXML.item) {
            var txtbox:Sprite = new Sprite();
            txtbox.graphics.beginFill(0x444444, 0.9);
            txtbox.graphics.drawRoundRect(0, 0, 100, 100, 15, 15)
            txtbox.graphics.endFill();
            txtbox.name = "txtbox_"+item.settings.target;
            addChild(txtbox);
            container.push(txtbox);
        }
        trace(container.length);
        // here your XML is loaded and processed. Dispatch an event to notify that job is done and container is not empty.
        dispatchEvent(new Event(Event.COMPLETE));
    }
}

在项目的某个地方,您可以创建此弹出窗口的实例:

//...
var popUp:PopUp = new PopUp();
popUp.addEventListener(Event.COMPLETE, onPopUpReady);
popUp.prepareAndLoad();
//...
private function onPopUpReady(e:Event):void {
    var popUp:PopUp = e.target as PopUp;
    trace(popUp.container.length); // Ready and loaded.
} 
//...

答案 1 :(得分:2)

阅读你的代码我可以看到第二个trace(container.length);返回0只是因为它在之前被称为"第一个" trace(container.length);

如果您看到函数FuncXML仅在第二个跟踪之前被声明并添加为侦听器回调(或处理程序),您可以理解它,但是因为您处于异步上下文中你永远不会知道FuncXML内容是否会在第二个"跟踪"之前执行。调用

特别是你有两个以并行运行的函数流:PopUpFuncXML流,但你假设它们是相应的。

希望这可以帮到你

答案 2 :(得分:-1)

如前所述,您在装货前正在寻找物品 你应该等到它们装好并准备就绪,然后在舞台上或其他地方处理它们。

我会像这样处理这种情况:
在您的主文件中:

var newTxt:PopUp = new PopUp({
    onReady_func: handlePopUp //pass the function to PopUp class as a parameter
}); 

// this function will be called whenever PopUp is ready
function handlePopUp(){
    trace(newTxt.container.length);
}

在PopUp类中:

...
// the $config object contains setup parameters 
public function PopUp($config) {
    ...
    function FuncXML(event:Event):void { 
       ...
       //  Everything is ready. Lets tell them.
       $config.onReady_func(); // this call should be in the last line of funcXML
    }