I am building a Flex application with a problem I am having with detecting whether or not a variable has been initialized. Observe this simplified code sample:
<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>
Based on the given code sample and comments, could someone please explain why this.pageObject always registers as not null, regardless of how many times the constructMenu() method is called or how many times the FoodMenu() class is instantiated?
Thank you for your time.
Edit: the full MXML as requested
<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>
One possible problem I see is with this piece of code :
The “this” pointer refers to something else(possibly the global object) in the closure.
Try the following to see for your self :