アプリケーションの奇妙な動作(ストロークXMPPとjqueryを使用)の後、jqueryイベントループは同期であり、例外を捕捉しないことがわかりました。
これは、最初のイベントハンドラが例外を発生させた場合、2番目のイベントハンドラは決して呼び出されないことを意味します。
$(document).ready(function() {
$(document).bind("foo", onFoo);
$(document).bind("bar", onBar);
$(document).trigger("foo");
$(document).trigger("bar");
});
function onFoo(e) {
console.log("listener onFoo");
throw "fail onFoo";
}
function onBar(e) {
console.log("listener onBar"); // not called
}
私たちは2つの出力を期待していましたが、2つ目の出力: "listener onBar"は決して表示されませんでした。
JQueryコードを参照してください。 "トリガー"関数では、ハンドラーのループ中にtry / catchパターンはありません。
while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
event.type = i > 1 ?
bubbleType :
special.bindType || type;
// jQuery handler
handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
if ( handle ) {
handle.apply( cur, data );
}
... (line 4998 in JQuery 1.10.2)
私たちはこの実装に驚いています。
純粋なjavascriptでは、ハンドラのどれかがクラッシュしても、すべてのハンドラが呼び出されます。 http://jsfiddle.net/bamthomas/kgS7A/2/.
誰かがJQueryチームが前のハンドラがクラッシュしても次のハンドラの実行を許可しない理由を知っていますか?なぜ例外がキャッチされないのですか?
なぜ彼らはjavascriptイベントハンドラを使用しませんでしたか?
回答:
回答№1は2これは、 このループは .dispatch
ソース:
while ((handleObj = matched.handlers[j++]) && !event.isImmediatePropagationStopped()) {
// Triggered event must either 1) have no namespace, or
// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
if (!event.namespace_re || event.namespace_re.test(handleObj.namespace)) {
event.handleObj = handleObj;
event.data = handleObj.data;
ret = ((jQuery.event.special[handleObj.origType] || {}).handle || handleObj.handler)
.apply(matched.elem, args);
if (ret !== undefined) {
if ((event.result = ret) === false) {
event.preventDefault();
event.stopPropagation();
}
}
}
ご覧のように、try / catchはありません .apply
.
彼らが望んでいたとしても、それを変更すると、あまりにも多くの既存のコードが破られます。恣意的に思えるjQueryの多くのものが、別の時間に生まれたことを忘れないでください。
もちろん、これを独自のコードで "修正"することができます(エラーメッセージでtry / catchでラップします)。しかし、あなたは他の誰よりも驚いています。