今回は、外部 SWF ファイルを読み込んだ際の、未処理エラーの扱いについての話です。
外部 SWF ファイルの未処理エラー
Loader オブジェクトを使って、外部の SWF ファイルを読み込んだ場合を想定します。このとき、読み込まれた側の SWF ファイル内で未処理のエラーが発生すると、SWF ファイルの階層内でイベントフローが発生します。
例えば、foo.swf が bar.swf を読み込んだとします。その状態で bar.swf 内で未処理のエラーが発生した場合、UncaughtErrorEvent イベントは、それぞれの SWF ファイルの Loader と LoaderInfo オブジェクト間で、以下の順にディスパッチされます。
- foo.swf の LoaderInfo (キャプチャフェーズ)
- foo.swf 内の Loader (キャプチャフェーズ)
- bar.swf の LoaderInfo (ターゲットフェーズ)
- foo.swf 内の Loader (バブリングフェーズ)
- foo.swf の LoaderInfo (バブリングフェーズ)
これにより、読み込んだ側の SWF ファイル (foo.swf) 内でも、読み込まれた側 (bar.swf) の未処理のエラーイベントを受け取ることができます。
(AS1/2 の SWF ファイルを読み込んだ場合は、UncaughtErrorEvent が発生しません。また、HTMLLoader 内に読み込んだ HTML コンテンツ内での JavaScript エラーも、イベントとして通知されません)
なので、未処理エラーの処理方針として、とりあえずエラーが受け取れればよい、という場合であれば、LoaderInfo にイベントハンドラーを追加するだけで OK ということになります。どの SWF で未処理のエラーが発生しても、最終的にバブリングフェーズで LoaderInfo に通知されるからです。(上のステップ 5)
一方、発生元の SWF ごとに受け取る箇所を分けたい、という場合には、
- 外部 SWF ファイルを読み込む Loader オブジェクトに UncaughtErrorEvent 用イベントハンドラーを追加
- そのハンドラー内で stopPropagation() を呼ぶ
とすると、自身の未処理エラーは LoaderInfo、読み込んだ SWF ファイルの未処理エラーはそれぞれの SWF ファイルが読み込まれている Loader、という分け方ができます。
下は、Loader オブジェクトで未処理のエラーを受け取る場合のサンプルです。
import flash.events.UncaughtErrorEvent;
public class UncaughtErrorEventExample extends Sprite
{
var loader:Loader;
public function LoaderUncaughtErrorEventExample()
{
loader = new Loader();
loader.uncaughtErrorEvents.addEventListener(
UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);
loader.load(new URLRequest("bar.swf"));
}
private function onUncaughtError(event:UncaughtErrorEvent):void
{
event.stopPropagation();
// エラー処理を記述
}
}
stopPropagation() の動作について
stopPropagation() メソッドを呼んだ場合、イベントフローは、その時点でターゲットとなっているオブジェクトで終わり、フローの後続のオブジェクトにはイベントが伝わりません。
UncaughtErrorEvent の場合は、この点がすこし異なります。Loader オブジェクトの UncaughtErrorEvents (末尾に s 付いてます) は、読み込まれた SWF 内の LoaderInfo の UncaughtErrorEvents とペアとして扱われます。先の例では、foo.swf 内の Loader と bar.swf の LoaderInfo がペアの関係になります。
そして、イベントフローがペアの LoaderInfo → Loader の順だったとして、LoaderInfo に登録されている UncaughtErrorEvent のイベントハンドラーが stopPropagation() を呼んだ場合、フローは LoaderInfo では止まらずにペアの Loader にも伝わってから終了します。
これに対して、stopImmediatePropagation() メソッドを呼んだ場合は、通常のイベントフローと同様に、その場でイベントフローが終了します。同じオブジェクトに登録されている他のイベントハンドラーも (まだ呼ばれていないものがあった場合) 呼ばれません。
デバッグ版でのエラーダイアログ
Flash Player や AIR のデバッグ版を使うと、未処理の実行時エラーが発生するたびに、ダイアログが表示されてエラー情報が通知されます。この動きは、UncaughtErrorEvent のイベントハンドラーを追加して、未処理のエラーを受け付けるようにしても変わりません。
エラーダイアログが表示されないようにしたいときは、イベントハンドラー内で UncaughtErrorEvent イベントに対して preventDefault() メソッドを呼ぶとよいようです。
コメントする