如何在Flex中捕获所有异常?

43
当我在调试Flash播放器中运行Flex应用程序时,如果发生意外情况,就会弹出异常弹窗。但是当客户使用应用程序时,他不会使用调试Flash播放器。在这种情况下,他不会收到异常弹窗,但UI不起作用。
因此,出于支持性的考虑,我想捕获Flex UI中可能发生的任何异常,并在Flex内部弹出窗口中显示错误消息。使用Java,我只需在try/catch块中封装整个UI代码,但是对于Flex中的MXML应用程序,我不知道在哪里可以执行这样的通用try/catch。
9个回答

52

在Flex 3中,没有办法接收未捕获异常的通知。Adobe公司已经意识到了这个问题,但我不知道他们是否有计划创建解决方法。

目前唯一的解决方案是在逻辑位置放置try/catch语句,并确保您正在监听发出它们的任何内容的ERROR(或对于Web服务来说是FAULT)事件。

编辑:此外,从事件处理程序抛出的错误实际上是无法捕获的。我已经在Adobe Bug系统上记录了一个bug

更新 2010-01-12:全局错误处理现在在Flash 10.1AIR 2.0(两者都是beta版)中得到支持,并且通过订阅LoaderInfo.uncaughtErrorEventsUNCAUGHT_ERROR事件来实现。下面的代码摘自livedocs上的代码示例

public class UncaughtErrorEventExample extends Sprite
{
    public function UncaughtErrorEventExample()
    {
        loaderInfo.uncaughtErrorEvents.addEventListener(
            UncaughtErrorEvent.UNCAUGHT_ERROR, uncaughtErrorHandler);
    }

    private function uncaughtErrorHandler(event:UncaughtErrorEvent):void
    {
        if (event.error is Error)
        {
            var error:Error = event.error as Error;
            // do something with the error
        }
        else if (event.error is ErrorEvent)
        {
            var errorEvent:ErrorEvent = event.error as ErrorEvent;
            // do something with the error
        }
        else
        {
            // a non-Error, non-ErrorEvent type was thrown and uncaught
        }
    }

2
我的上面的代码需要Flex 4。但是,如果您使用((IEventDispatcher)loaderInfo["uncaughtErrorEvents"]).addEventListener("uncaughtError", handlerFunction),则它应该在任何运行对10.1 SDK的SDK中工作,因为这些属性将在播放器的运行时存在。您甚至可以使用if (loaderInfo.hasProperty("uncaughtErrorEvents") { }进行包装,以确保它不会在Flash 9/10中出现问题(当然,错误处理将不起作用,但它不会崩溃)。 - Richard Szalay
1
@Richard的评论:这确实是你期望它工作的方式,但不幸的是,它并没有。如果你以Flash Player 9为目标进行编译,并在Flash Player 10.1上运行它,loaderInfo [“uncaughtErrorEvents”]仍然不可用!我的解释:Flash播放器在运行时查看您的swf针对哪个播放器,并“隐藏”尚未出现在该版本中的功能。 - Wouter Coekaerts
@Wouter - 我也遇到了这个问题。请随意投票/添加评论到我的错误报告中:https://bugs.adobe.com/jira/browse/FB-27199 - Richard Szalay
3
补充回答:如果您正在运行Flash Player的调试版本,通用运行时错误对话框仍然会弹出。为了防止此情况发生,请在全局错误处理程序中调用event.preventDefault()。 - Christophe Herreman
如果您添加了verbose-stacktraces编译器选项,您将会得到生产SWF文件的堆栈跟踪(尽管SWF文件会稍微变大一些)。 - Clintm
显示剩余3条评论

9

4

这在Flex 3.3中有效。

 if(loaderInfo.hasOwnProperty("uncaughtErrorEvents")){
    IEventDispatcher(loaderInfo["uncaughtErrorEvents"]).addEventListener("uncaughtError", uncaughtErrorHandler);
 }

3

它适用于Flex 3.5和Flash Player 10:

  <?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" addedToStage="application1_addedToStageHandler(event)">
    <mx:Script>
        <![CDATA[
            import mx.events.FlexEvent;
            
            protected function application1_addedToStageHandler(event:Event):void{              
                if(loaderInfo.hasOwnProperty("uncaughtErrorEvents")){
                    IEventDispatcher(loaderInfo["uncaughtErrorEvents"]).addEventListener("uncaughtError", uncaughtErrorHandler);
                }
                
                sdk.text = "Flex " + mx_internal::VERSION;
            }
            
            private function uncaughtErrorHandler(e:*):void{
                e.preventDefault();
                
                var s:String;

                if (e.error is Error)
                {
                    var error:Error = e.error as Error;
                    s = "Uncaught Error: " + error.errorID + ", " + error.name + ", " + error.message;
                }
                else
                {
                    var errorEvent:ErrorEvent = e.error as ErrorEvent;
                    s = "Uncaught ErrorEvent: " + errorEvent.text;
                }
                
                msg.text = s;
            }
            
            private function unCaught():void
            {
                var foo:String = null;
                trace(foo.length);
            }
        ]]>
    </mx:Script>
    <mx:VBox>
        <mx:Label id="sdk" fontSize="18"/>
        <mx:Button y="50" label="UnCaught Error" click="unCaught();" />
        <mx:TextArea id="msg" width="180" height="70"/>
    </mx:VBox>
</mx:Application>

谢谢


3
我正在使用flex 4。 我尝试了loaderInfo.UncaughtErrorEvents,但loaderInfo未初始化,因此导致了空引用错误。然后我尝试了root.loaderInfo.UncaughtErrorEvents,结果还是一样。 我尝试了sprite.root.UncaughtErrorEvents,但是没有sprite对象,我创建了一个,但是它没有起作用。最后我尝试了 systemManager.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR,globalUnCaughtErrorHandler.hanleUnCaughtError); 猜猜怎么着,它就像魔术一样奏效了。 检查这里

3

3
与接受的答案不同,使用try-catch。我认为这种方法更慢但更容易阅读。
try {
    loaderInfo.uncaughtErrorEvents.addEventListener("uncaughtError", onUncaughtError);
} catch (e:ReferenceError) {
    var spl:Array = Capabilities.version.split(" ");
    var verSpl:Array = spl[1].split(",");

    if (int(verSpl[0]) >= 10 &&
        int(verSpl[1]) >= 1) {
        // This version is 10.1 or greater - we should have been able to listen for uncaught errors...
        d.warn("Unable to listen for uncaught error events, despite flash version: " + Capabilities.version);
    }
}

当然,要成功编译此代码,您需要使用最新的10.1 playerglobal.swc:http://labs.adobe.com/downloads/flashplayer10.html

2

我将事件监听器附加到了“root”,这对我起作用:

sprite.root.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);

在调试Flash Player中,这仍然会出错,但在非调试版本中,错误将出现在Flash Player的对话框中 - 然后处理程序将做出响应。要停止对话框的出现,请添加:
event.preventDefault();

所以:
    private function onUncaughtError(event:UncaughtErrorEvent):void
    {
        event.preventDefault();
        // do something with this error
    }

我之前在AIR中使用过这个方法,但我认为它也适用于标准的AS3项目。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接