ようやく、Flash Player 10.1 の新機能の話です。
前回までは、実行時エラーには、同期/非同期の 2 種類があること、それぞれ catch ブロックまたはイベントハンドラーを使って処理すること、という話でした。
Flash Player 10.1 と AIR 2 からは、「実行時エラーが発生したが catch ブロックにもイベントハンドラーにも渡されなかった」 という状況が起きると、UncaughtErrorEvent が生成されます。これにより、処理されなかったエラーの情報が通知されるため、エラー処理をこまごまと記述しなくても、とりあえずどんなエラーが起きたのかを知ることができます。
とはいえ、同期エラーが起きた場合であれば、スクリプトの実行が途中で終わってしまっている可能性があります。また、非同期エラーだった場合も、エラーの原因となったりソースにアクセスできるとは限りません。
つまり、グローバルエラーハンドラーは、状況を知るのには役立ちますが、それで問題が解決できるかというと、それはまた別の話なのです。アプリケーションが不安定になるようなエラーに対しては、やはり明示的なエラー処理の記述が必要そうです。(あたりまえですが)
UncaughtErrorEvent ハンドラーの追加
さて、UncaughtErrorEvent は、以下の 2 つのオブジェクトからディスパッチされます。
- LoaderInfo.uncaughtErrorEvents
SWF 自身のコードによる未処理のエラーを通知 - Loader.uncaughtErrorEvents
Loader に読み込んだ SWF 内のコードによる未処理のエラーを通知
どちらのオブジェクトも UncaughtErrorEvents オブジェクトです。UncaughtErrorEvents は EventDispatcher のサブクラスで UncaughtErrorEvent ディスパッチ専用のクラスです。(ディスパッチする側とされる側の違いが、名前の最後の s の有無だけなのです。ややこしい)
ともあれ、これらのオブジェクトにイベントハンドラーを追加すればよいわけです
LoaderInfo に UncaughtErrorEvent イベントハンドラーを追加するときは、コンストラクタ内で行うのがよいと思われます。
import flash.events.UncaughtErrorEvent; public class UncaughtErrorEventExample extends Sprite { public function UncaughtErrorEventExample() { loaderInfo.uncaughtErrorEvents.addEventListener( UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError); } private function onUncaughtError(event:UncaughtErrorEvent):void { // エラー処理を記述 } }
Flex の場合は、ApplicationComplete イベントのタイミングで追加する、という感じでしょうか。
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
applicationComplete="onApplicationComplete();">
<fx:Script>
<![CDATA[ import flash.events.UncaughtErrorEvent; private function onApplicationComplete():void { loaderInfo.uncaughtErrorEvents.addEventListener( UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError); } private function onUncaughtError(event:UncaughtErrorEvent):void { // エラー処理を記述 } ]]>
</fx:Script>
</s:WindowedApplication>
イベントハンドラーの書き方についてですが、
UncaughtErrorEvent には error という属性があり、ここに未処理のエラーオブジェクト、すなわち Error オブジェクト (同期エラーの場合) や ErrorEvent オブジェクト (非同期エラーの場合) が設定されます。
ただし、以前の記事にも書いたように、スクリプトから任意の型のオブジェクトを throw することが可能です。なので、UncaughtErrorEvent のハンドラーでは、Error、ErrorEvent、それ以外、の 3 種類の (最低でも) オブジェクトを扱えるようにします。
function onUncaughtError(event:UncaughtErrorEvent):void { var message:String; if (event.error is Error) { message = Error(event.error).message; } else if (event.error is ErrorEvent) { message = ErrorEvent(event.error).text; } else { message = event.error.toString(); } }
8/11 追記: ステータスイベントによるエラー通知 (NetStatusEvent.info.level や StatusEvent.level の値が error) の場合には、エラーが未処理でも UncaughtErrorEvent がディスパッチされません。イベントハンドラー内に、ステータスイベントを扱うための記述は不要です。
Loader に読み込んだ外部 SWF のグローバルエラーハンドラー使用については、次回に続きます。
コメントする