为什么Jquery事件循环在异常时被中断

Sté*_*car 8 javascript jquery javascript-events

在我们的应用程序奇怪的行为(使用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
}
Run Code Online (Sandbox Code Playgroud)

我们期望看到两个输出,但第二个输出:"监听器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)
Run Code Online (Sandbox Code Playgroud)

我们对此实施感到惊讶.

在纯javascript中,即使其中一个崩溃,也会调用所有处理程序:http://jsfiddle.net/bamthomas/kgS7A/2/.

有人知道为什么JQuery团队不允许执行下一个处理程序,即使前一个处理程序崩溃了吗?为什么没有例外?

他们为什么不使用javascript事件处理程序?

Ben*_*aum 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();
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,周围没有 try/catch .apply

多年来一直如此

即使他们愿意,现在更改它也会破坏太多现有代码。请记住,jQuery 中的许多现在看来任意的东西都是在另一个时代诞生的。

当然,您可以在自己的代码中“修复”此问题(将其包装在带有错误消息的 try/catch 中),但您会让其他所有人感到惊讶。