0

我正在构建一个 Flex 应用程序,但在检测变量是否已初始化时遇到了问题。观察这个简化的代码示例:

<fx:Script>
  <![CDATA[
    private var pageObject:* = null; //Yes the "*" data type is needed ;)

  //Fired by the application elseware
    private function constructMenu(e:ResultEvent):void {
      if (this.pageObject != null) {
        //This block never runs...

        // The pageObject will be null when the application
        // first runs, so skip this first time around.
        // However... this method will be called multiple
        // times. Since FoodMenu() is a display object
        // and is instantiated below, all subsequent calls
        // to this method will require us to remove the old
        // display object before adding a new one.
      } else {
        // This block always runs...
      }

      setTimeout(function():void {
        this.pageObject = new FoodMenu(); //Should now be not-null!!!

        //Do more stuff with the FoodMenu() and add to the main application
      }, 1000);
    }
  ]]>
</fx:Script>

根据给定的代码示例和注释,有人可以解释为什么this.pageObject总是注册为非空,不管constructMenu()方法被调用多少次或FoodMenu()类被实例化多少次?

感谢您的时间。

编辑:按要求提供完整的 MXML

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
           xmlns:s="library://ns.adobe.com/flex/spark"
           xmlns:mx="library://ns.adobe.com/flex/mx"
           xmlns:components="components.*"
           xmlns:pagesservice="services.pagesservice.*"
           xmlns:menuservice="services.menuservice.*"
           minWidth="955" minHeight="600" backgroundColor="0x141414"
           creationComplete="init(event)" skinClass="skins.Theme" xmlns:pages="components.pages.*" xmlns:reviewsservice="services.reviewsservice.*">
<fx:Script>
    <![CDATA[
        import com.asual.swfaddress.*;
        import com.forwardfour.boncuisson.events.MenuEvent;
        import com.greensock.TweenMax;
        import com.greensock.plugins.VisiblePlugin;

        import components.header.Menu;
        import components.pages.FoodMenu;

        import flash.utils.setTimeout;

        import mx.controls.Alert;
        import mx.core.IVisualElement;
        import mx.events.FlexEvent;
        import mx.rpc.events.FaultEvent;
        import mx.rpc.events.ResultEvent;

        import skins.Theme;

        import spark.components.Group;

    //Globalize a reference to the navigation menu
        private var menu:Menu;

    //Globalize a reference to the page content
        private var pageObject:* = null; //This reference will be various types, so just make a general object

    /**
     * Initialization
     * -------------------------------
    */

    //Add an event listener for when "links" on the menu are clicked and initialize SWFAddress
        private function init(event:FlexEvent):void {
        //Listen for menu clicks
            var skin:Theme = Theme(this.skin);
            this.menu = Menu(skin.menu);
            this.menu.addEventListener(Menu.MENU_ITEM_CLICKED, menuNavigateToPageHandler);

        //Initialize SWFAddress
            SWFAddress.addEventListener(SWFAddressEvent.INIT, initSWFAddress);
        }

    //Initialize SWFAddress and grab the page listed from the URL
        private function initSWFAddress(e:SWFAddressEvent):void {
        //Listen for change events
            SWFAddress.addEventListener(SWFAddressEvent.CHANGE, URLNavigateToPageHandler);

        //Fetch the page from the URL
            var URL:String = SWFAddress.getValue();

            if (URL == "" || URL == "/") {
                pagesResponder.token = page.getPagesByPosition(1);
            } else {
                pagesResponder.token = page.getPagesByURL(URL.substring(1));
            }
        }

    /**
     * Navigation handlers
     * -------------------------------
    */

    //Go to a specific page when a menu item has been clicked
        private function menuNavigateToPageHandler(e:MenuEvent):void {
            SWFAddress.setValue(e.pageURL);
            pagesResponder.token = page.getPagesByID(e.pageID);
        }

    //Request a page when the URL has changed
        private function URLNavigateToPageHandler(e:SWFAddressEvent):void {
            var URL:String = SWFAddress.getValue();

            if (URL == "" || URL == "/") {
                pagesResponder.token = page.getPagesByPosition(1);
            } else {
                pagesResponder.token = page.getPagesByURL(URL.substring(1));
            }
        }   

    /**
     * Loading content
     * -------------------------------
    */  

    //Show an error dialog in the case of an error when communicating with the server
        private function requestErrorHandler(e:FaultEvent):void {
            Alert.show("Fault string: " + e.fault.faultString + "\nFault detail: " + e.fault.faultDetail, e.fault.faultCode);
        }   

    //Determine what kind of page will be constructed
        private function determinePage(e:ResultEvent):void {
            var pageType:String = pagesResponder.lastResult.type;

        //We will need to know the type of page to build
            switch(pageType) {
                case "menu" : 
                    menuResponder.token = menuFetch.getMenuByType(pagesResponder.lastResult.category);
                    break;

                case "lunch" : 
                    break;

                case "reviews" : 
                    reviewsResponder.token = reviews.getAllReviews();
                    break;

                case "home" : 
                default : 
                    break;
            }
        }

    //Using the data that was fetched from the "menuFetch" service, construct the page of type menu
        private function constructMenu(e:ResultEvent):void {
        //Transition the existing page out of view
            if (this.pageObject != null) {
                Alert.show("i");
                TweenMax.to(this.pageObject, 0.75, {
                    alpha : 0,
                    y : 20
                });


                removeElement(this.pageObject);
            }

            setTimeout(function():void {
                this.pageObject = new FoodMenu();
                this.pageObject.alpha = 0;
                this.pageObject.y = 20;
                this.pageObject.data = menuResponder.lastResult;
                addElement(this.pageObject);

            //Tween the new menu into place
                TweenMax.to(this.pageObject, 0.75, {
                    alpha : 1,
                    y : 0
                });
            }, 1000);
        }
    ]]>
</fx:Script>

<!-- Make a request to the server for the page data -->
<fx:Declarations>
    <pagesservice:PagesService id="page"/>
    <s:CallResponder id="pagesResponder" fault="requestErrorHandler(event)" result="determinePage(event)"/>

    <menuservice:MenuService id="menuFetch"/>
    <s:CallResponder id="menuResponder" fault="requestErrorHandler(event)" result="constructMenu(event)"/>

    <reviewsservice:ReviewsService id="reviews"/>
    <s:CallResponder id="reviewsResponder" fault="requestErrorHandler(event)" result="constructMenu(event)"/>
</fx:Declarations>
</s:Application>
4

1 回答 1

2

我看到的一个可能的问题是这段代码:

setTimeout(function():void {
   this.pageObject = new FoodMenu(); //Should now be not-null!!!
   //Do more stuff with the FoodMenu() and add to the main application
}, 1000);

“this”指针指向闭包中的其他东西(可能是全局对象)。

尝试以下方法来亲自查看:

trace(this);
setTimeout(function():void {
    trace(this);
},1000);
于 2012-07-22T21:00:47.130 回答