Variable dispatch is not defined - actionscript-3

I'm getting an anoying error while triying to dispatch a custom Event.
What I'm triying is this:
1- Setting a listener in a .as file.
import flash.events.Event;
emisor.addEventListener("accionTerminada", onAccionTerminada)
function onAccionTerminada(evento:Event):void{
trace("Accion Terminada");
}
2- Launching the event in another .as
dispatchEvent(new Event("accionTerminada"));
But I don't know why I'm getting the following error
ReferenceError: Error #1065: Variable dispatchEvent is not defined.
Don't know why its passing dispatchEvent as a variable instead of a function...
Also tried dispatch having the same error.
Thanks
EDIT:
The other .as.
public class CustomPalManager implements IProvideCustomPalList, IManageCustomPal {
[Inject]
public var space:CurrentSpaceCustomPal;
private var _collection:VectorCollection;
public function remove(target:CustomPalVO):void {
var index:int = space.value.content.indexOf(target);
if (index != -1) {
space.value.content.splice(index, 1);
collection.refresh();
//dispatchEvent(new Event("updateAfterDelete"));
} else {
throw new ArgumentError("Impossible to remove wall, it doesn't exist");
}
}
}
}

Related

Avoid null object reference errors in code inside the child SWF

I'm creating a global loader that loads different SWFs.
I don't have access to the child SWFs code.
I'm trying to avoid null object reference errors in code inside the child SWF that may reference "stage" etc.
I've added all the possible event listeners, added try/catch, tried all the applicationDomains and LoaderContexts permutations. for example:
applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);
var con:LoaderContext = new LoaderContext(false, applicationDomain );
con.allowCodeImport = true;
var _loader:Loader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoad);
_loader.load( new URLRequest(fileName + ".swf"), con);
I just can't catch the error or disable/remove the code from such a SWF.
for example, the following Main class:
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public function Main() {
var h = this.stage.stageHeight;
trace(h);
}
}
}
will crush any SWF that will try to load it as part of another SWF.
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Main()
Any help with catching the Error, disabling/removing the code or any other idea will be much appreciated.
Thanks.
Do you have access to the code in the child swf files? If so, you can do something like this:
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public function Main() {
if (stage) {
init();
}
else {
addEventListener(Event.ADDED_TO_STAGE, init);
}
}
public function init(evt:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
// You can now access the stage here
}
}
}
This will hold off initializing the child object until the stage reference is set. For all child objects the constructor will be called first before the stage is set, so you can't rely on it being there in the constructor.

In ActionScript3, how to catch ErrorEvent that I've dispatched?

At some points in my application, I've a try-catch block such as:
This happens inside classes that are not in the display list (not Sprites, nor any kind of DisplayObject), but extend EventDispatcher.
Those classes reside in externally loaded SWF (in case that matters).
try {
... some logic that may throw Error
} catch (e:Error) {
var errorEvent:ErrorEvent = new ErrorEvent(ErrorEvent.ERROR, true);
errorEvent.text = e.getStackTrace();
dispatchEvent(errorEvent);
}
In the root class, this is what I have:
loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtErrorHandler);
loaderInfo.uncaughtErrorEvents.addEventListener(ErrorEvent.ERROR, onErrorEventHandler);
stage.addEventListener(ErrorEvent.ERROR, onErrorEventHandler);
protected function onUncaughtErrorHandler(event:UncaughtErrorEvent):void
{
var message:String;
if (event.error is Error) {
message = event.error.getStackTrace();
} else if (event.error is ErrorEvent) {
message = ErrorEvent(event.error).text;
} else {
message = event.error.toString();
}
trace(message);
}
protected function onErrorEventHandler(event:ErrorEvent):void
{
trace(event.text);
}
Neither handlers are called, but those error events bubble up and I see them in console, and as popups in debug mode, but how do I listen to them in a root class?
I do this because I don't want the error to interrupt execution of the main thread or the particular business logic.
I think what you are looking for is a listener to uncaught error events. Here is an example of adding it in your root class:
this.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onGlobalErrors);
EDIT BY LDMS
The following works in FlashPro:
loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR,function(e:Event){
trace("I Caught an Error");
});
var err:ErrorEvent = new ErrorEvent(ErrorEvent.ERROR,true);
var obj:EventDispatcher = new EventDispatcher();
obj.dispatchEvent(err);
If your class is on stage you can add event listener for ErrorEvent.ERROR to stage. Any dispatched event will go up to the stage through all its parents.
Example of code:
// some initialize
stage.addEventListener("lol", lolHandler);
// dispatching
private function button1_clickHandler(event:MouseEvent):void
{
// second parameter responsible for bubbling and MUST be true
dispatchEvent(new Event("lol", true)); // on mouseClick we dispatch custom event
}
private function lolHandler(event:Event):void
{
trace("We got it! Lol!);
}
P.S. Article in the comment is really useful. Recommend it to read.
// UPDATE
Alternative variant can be in dispatching event from some singleton. For example:
public class ErrorHandler extends EventDispatcher {
private static var _instance:ErrorHandler;
public static function get instance():ErrorHandler {
if (!_instance)
_instance = new ErrorHandler(new PrivateConstructor());
return _instance;
}
public function ErrorHandler(value:PrivateConstructor) {
addEventListener(ErrorEvent.ERROR, errorHandler);
}
private function errorHandler(event:ErrorEvent):void {
// some code
}
}
}
class PrivateConstructor {}
.... and dispatching
ErrorHandler.instance.dispatchEvent(new ErrorEvent());

Flash AS3 Loadmovie Error #1009 - External AS file

We have created a program in Flash that uses an external actionscript file.
I'm trying to load/import this swf in another flash file but I'm getting a 'Error #1009: Cannot access a property or method of a null object reference'
I know this is to a reference in my external .as file but I'm not sure how to fix this
This is my code to load (and scale) the swf
var ld:Loader = new Loader();
addChild(ld);
ld.load(new URLRequest("tatton.swf"));
ld.contentLoaderInfo.addEventListener(Event.COMPLETE,function(evt) {
var mc = evt.target.content;
mc.scaleX=0.7031;
mc.scaleY=0.7031;
});
Anyone have any ideas?
Thanks
Edit: here is the full error code: TypeError: Error #1009: Cannot access a property or method of a null object reference. at Tatton()
And below is my .as file code:
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.utils.setTimeout;
import flash.utils.clearTimeout;
import flash.utils.getDefinitionByName;
public class Tatton extends MovieClip
{
public var active_clip:MovieClip;
public var to:Number;
public function Tatton()
{
// Create empty vector of movieclips;
stage.addEventListener(MouseEvent.CLICK, reset_timeout);
init();
}
public function reset_timeout(e:Event = null)
{
clearTimeout(to);
// 3 mins
to = setTimeout(fire_timeout, 150 * 1000);
}
public function fire_timeout():void
{
// Reset the system (and run attractor) if we're not on the attractor already.
if ( !(active_clip is Attractor))
{
init();
}
}
public function init()
{
// Reset globals
Globals.skip_menu_anim = false;
Globals.skip_staff_menu = false;
load_movie("Attractor");
reset_timeout();
}
public function load_movie(name:String):void
{
if (active_clip is MovieClip)
{
kill_active_movie();
}
active_clip = createInstance(name);
addChild(active_clip);
active_clip.startup();
}
public function kill_active_movie():void
{
active_clip.shutdown();
removeChild(active_clip);
active_clip = null;
}
public function createInstance(className:String):Object
{
var myClass:Class = getDefinitionByName(className) as Class;
var instance:Object = new myClass();
return instance;
}
}
}
try this
public function Tatton() {
addEventListener(Event.ADDED_TO_STAGE, stageAvailable);
}
private function stageAvailable(e:Event = null) {
removeEventListener(Event.ADDED_TO_STAGE, stageAvailable);
// Create empty vector of movieclips;
stage.addEventListener(MouseEvent.CLICK, reset_timeout);
init();
}
refer to this article to understand why
You need to add the event listener after you call Loader.load because contentLoaderInfo is null until load is called.

Flex 4 disptaching custom event from custom component (why flex converting custom event to mouseevent)

This is NOT duplicate of my earlier post (its is slightly different)
But this is similar issue with similar error but its not the same error
The error I am getting now is below while dispatching the custom event from my custom component
TypeError: Error #1034: Type Coercion failed: cannot convert events::MapEvent#a74ab51 to flash.events.MouseEvent.
dispatchEvent(new MapEvent(MapEvent.CLICKED_ON_MAP));
Note: The error in my earlier post is giving below error message
Type Coercion failed: cannot convert flash.events::Event#81ecb79 to com.events.ShopEvent
The difference here are two things, the earlier error is while converting flash event to custom event and now this one is while converting custom event to flash event and secondly, I have no clue why it is trying to convert to the mouseevent where I am just dispatching my custom event with proper listeners.
Can some one correct me what I am doing wrong here.
This is my custome event
package events
{
import flash.events.Event;
import ui.map.MapElement;
public class MapEvent extends Event
{
public static const NEW_ELEMENT_ATTACHED:String = "newElementAttached";
public static const CLICKED_ON_MAP:String = "clickedOnMap";
public static const CLICKED_ON_ELEMENT:String = "clickedOnElement";
public var element:MapElement;
public function MapEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false){
super(type, bubbles, cancelable);
}
override public function clone():Event{
var c:MapEvent = new MapEvent(type, bubbles, cancelable);
c.element = this.element;
return c;
}
}
}
This is how I am dispatching the event from my custom component (WorldMap.as class file)
private function clickHandler(e:MouseEvent):void{
e.stopImmediatePropagation();
trace("worldmap click handler");
if (dragInProgress){
/*trace ("stopping event propagation");*/
dragInProgress = false;
return;
}else{
trace("dispatching proxy click event");
dispatchEvent(new MapEvent(MapEvent.CLICKED_ON_MAP));
}
}
I have declared [Event] metatag as well
[Event(name="newElementAttached", type="events.MapEvent")]
[Event(name="clickedOnMap", type="events.MapEvent")]
[Event(name="clickedOnElement", type="events.MapEvent")]
Finally the listener is attached in other component (controller.as)
_userWorld.addEventListener(MapEvent.CLICKED_ON_MAP,clickedOnWorldMap);
_userWorld.addEventListener(MapEvent.CLICKED_ON_ELEMENT,clickedOnElement);
private function clickedOnWorldMap(e:MouseEvent):void{
_draggingMapElement.hideBaseGrid();
_draggingMapElement = null;
}
private function clickedOnElement(e:MapEvent):void{
}
Its my bad. I fixed the silly bug.
I changed the lister function definition. (Replace mouseevent to MapEvent)
private function clickedOnWorldMap(e:MapEvent):void{
_draggingMapElement.hideBaseGrid();
_draggingMapElement = null;
}

AS3 Error reporting from event callback

I have been experimenting with supplying better debugging information when an error happens in asynchronous code in AS3.
As an example of the poor error reporting be default, take the case where I force a null pointer in a Timer callback (github gist), I get the following stacktrace back on the console:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Function/<anonymous>()[/[path-to-source-file]/TestClass.as:14]
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()
This tells me very little about how the timer callback actually links to my code.
The question is: How can I get information about what code created the callback?
I have added one of my solutions below. I'm interested to see if this can be improved.
One possible solution is to pre-create an Error object in the consumer "thread"/"scope"
var errorInConsumerScope:Error = new Error()
var timer:Timer = new Timer(1000, 1)
timer.addEventListener(TimerEvent.TIMER, internalCallback)
timer.start()
function internalCallback(e:TimerEvent):void
{
try
{
// do something that could cause an error
}
catch (e:Error)
{
errorInConsumerScope.message = e.message
throw errorInConsumerScope
}
}
This now gives me the stacktrace back into my calling code:
Error: Error #1009: Cannot access a property or method of a null object reference.
at TestClass()[/[path-to-source-file]/TestClass.as:10]
at Main()[/[path-to-source-file]/Main.as:9]
The complete gist is here
Interesting thing.
The doc to Error.getStackTrace() says:
Returns the call stack for an error as a string at the time of the
error's construction
According to this, the stacktrace works as expected. The error is constructed in your event handler which is called by the timer tick event.
In your second example you create the error to be dispatched in the constructor of the TestClass. So your stacktrace will show the chain up to the TestClass constructor.
You probably ask for a general solution. I would go with unit tests and proper debugging using breakpoints and object inspection. But here another idea:
TestClass:
package {
import flash.events.TimerEvent;
import flash.utils.Timer;
public class TestClass {
public function TestClass(userCallback : Function, fail : Function) {
var timer : Timer = new Timer(1000, 1);
timer.addEventListener(TimerEvent.TIMER, internalCallback);
timer.start();
function internalCallback(e : TimerEvent):void {
try {
var nullProperty : String;
nullProperty.length;
} catch (e:Error) {
fail();
return;
}
userCallback();
}
}
}
}
Main:
package {
import flash.display.Sprite;
public class Main extends Sprite {
public function Main() {
new TestClass(
function() : void { trace('Call me back when your done.'); },
function() : void { throw new Error('Something went wrong.'); }
);
}
}
}
Output:
Exception fault: Error: Something went wrong.
at Function/<anonymous>()[Main.as:8]
at Function/TestClass/$construct/internalCallback()[TestClass.as:16]
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()