在我们的应用程序出现奇怪的行为之后(使用strophe XMPP和jquery),我们发现jquery事件循环是同步的,不会捕获异常。
这意味着如果第一个事件处理程序引发异常,则永远不会调用第二个事件处理程序。
$(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
}
我们希望看到两个输出,但第二个输出:"监听器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事件处理程序?
答案 0 :(得分:2)
这是因为this loop taken from the .dispatch
source:
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();
}
}
}
正如您所看到的,.apply
周围没有尝试/捕获。
这就是years和years and years的方式。
即使他们想要,现在更改它也会破坏太多的现有代码。请记住,jQuery中很多看似随意的东西现在都是在另一个时代诞生的。
您当然可以在自己的代码中“修复”此问题(将其包装在带有错误消息的try / catch中),但是您会对其他所有人感到惊讶。