1

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.

Martin Asenov
  • 1,288
  • 2
  • 20
  • 38
  • @WillKru well, I want to listen to them in a root class, I edited the question – Martin Asenov Sep 18 '14 at 14:45
  • 1
    You need to research 'bubbling' and how that works with [error handling in actionscript](http://www.adobe.com/devnet/actionscript/articles/event_handling_as3.html) to fully grasp proper error handling – Anil Sep 18 '14 at 14:48
  • @SlyRaskal I can't find examples of that particular case... What I do, is dispatch event is some class that is not directly referenced in the root class, so I can't "addEventListener" to it. However, I want to catch it there and log it. I see it bubbles, but where? That's what I'm asking. Thank you – Martin Asenov Sep 18 '14 at 14:59
  • You event isn't going to bubble because you are not telling it to. You'll need to listen on the capture phase, or tell it to bubble with the second parameter: `new ErrorEvent(ErrorEvent.ERROR, true);` Is your code example part of an object that's on the display list? If not the event won't make it to the stage/root. How are you listening for this error event currently? – BadFeelingAboutThis Sep 18 '14 at 16:36
  • Also, using `LoaderInfo.uncaughtErrorEvent` will work - not sure why you think otherwise... – BadFeelingAboutThis Sep 18 '14 at 16:41
  • @LDMS the object that dispatches it is not part of the display list. The event bubbles, because I see both popup and console alert for it. LoaderInfo.uncaughtErrorEvent doesn't work because the error does not come from loading a file via Loader or URLLoader – Martin Asenov Sep 18 '14 at 17:44
  • @MartinAsenov - It Doesn't matter if your loading a file, uncaughtErrorEvent will catch any `ErrorEvent` object including ones you create. Without being a part of the display list, there is nothing to bubble up to and in your code provided you haven't enable bubbling anyway. You need to either put it on the display list, or pass in a reference to something that is on the display list (or the stage itself) and dispatch the event on it. Or use the uncaught error event handler – BadFeelingAboutThis Sep 18 '14 at 17:48
  • @LDMS This is not true, if you like you can try it yourself... I listen to both loaderInfo.uncaughtErrorEvents and stage, for event type ErrorEvent.ERROR, which is dispatched with bubbles=true, still doesn't get caught anywhere – Martin Asenov Sep 18 '14 at 17:53
  • @MartinAsenov - I have tried it. Your implementation must be wrong. Provide more code and perhaps someone can help more. – BadFeelingAboutThis Sep 18 '14 at 17:55
  • Likely it being an externally loaded swf that is the issue (with uncaughterror event), as it may be getting caught on child swf's loaderInfo not the root one. When you load the child swf, add the listener to it's loaderInfo object. – BadFeelingAboutThis Sep 18 '14 at 19:11

2 Answers2

2

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);
BadFeelingAboutThis
  • 14,445
  • 2
  • 33
  • 40
  • as I already said, this won't work, because the EventError does not occur when loading a file via Loader or URLLoader. These errors are handled via loaderInfo, yes, but this one will be not. why the +1? – Martin Asenov Sep 18 '14 at 17:45
  • @MartinAsenov - You are wrong. I gave the +1 because this is the best way to handle this situation – BadFeelingAboutThis Sep 18 '14 at 17:53
  • 1
    LoaderInfo object contains a lot of data about a loaded SWF file. In this case you are accessing loaderInfo of your root class, i.e. of your whole SWF. That's why it will catch the unhandled errors. Look here: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/LoaderInfo.html#uncaughtErrorEvents – Aleksey Linetskiy Sep 18 '14 at 18:00
  • guys, I edited the question. The code that is there does not catch any event. – Martin Asenov Sep 18 '14 at 18:07
0

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());
Crabar
  • 1,829
  • 1
  • 14
  • 26
  • the class I dispatch the event is not in the display list , so it won't be dispatched to stage – Martin Asenov Sep 18 '14 at 17:47
  • yes, Crabar this will work, but however we can use the built-in event bubbling functionality in AS3. This may be solution if everything else fails. Thank you! – Martin Asenov Sep 18 '14 at 18:07
  • You cannot use bubbling if class is not in display list. But you can re-dispath event. – Crabar Sep 18 '14 at 18:11