2014-04-10 10 views
8

Nach einem seltsamen Verhalten unserer Anwendung (mit Strophe XMPP und jquery) haben wir festgestellt, dass die jquery-Ereignisschleife synchron ist und keine Ausnahme abfängt.Warum Jquery-Ereignisschleife bei Ausnahme unterbrochen wird

Es bedeutet, dass, wenn der erste Ereignishandler eine Ausnahme auslöst, der zweite nie aufgerufen wird.

Wir erwarteten zwei Ausgaben, aber die zweite: "Listener onBar" wurde nie angezeigt.

Siehe JQuery-Code, in der "Trigger" -Funktion gibt es kein Try/Catch-Muster während der Schleife der Handler.

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) 

Wir waren von dieser Implementierung überrascht. In reinem Javascript werden alle Handler aufgerufen, selbst wenn einer von ihnen abgestürzt ist: http://jsfiddle.net/bamthomas/kgS7A/2/.

Weiß jemand, warum das JQuery-Team die Ausführung des nächsten Handlers nicht erlaubt, selbst wenn der vorherige abgestürzt ist? Warum werden Ausnahmen nicht eingefangen?

Warum haben sie Javascript Event-Handler nicht verwendet?

+0

"Warum fängt jQuery keine Ausnahmen?" Wahrscheinlich liegt das daran, dass niemand dachte, dass dies ein Problem sein könnte. Sie können gerne eine Pull-Anfrage an ihr Github-Repository senden. –

+0

Wenn Ihr Event-Handler auslösen kann, liegt es in Ihrer Verantwortung, die Ausnahme zu erfassen. Warum würdest du erwarten (oder wollen), dass 'Trigger' das tut? – Tomalak

+0

So viel wie die Entdeckung, dass jQuery Ausnahmen nicht abfangen kann nützlich sein, ich glaube nicht, dass diese Frage objektiv beantwortet werden kann ... –

Antwort

2

Das geschieht wegen 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(); 
      } 
     } 
} 

Wie Sie sehen können, gibt es keine try/catch um .apply.

So war es für years und years and years.

Selbst wenn sie wollten, wird das Ändern jetzt zu viel vorhandenen Code zerstören. Denken Sie daran, viele Dinge in jQuery, die jetzt willkürlich scheinen, wurden in einer anderen Zeit geboren.

Sie können dies natürlich in Ihrem eigenen Code beheben (indem Sie es in einen try/catch mit Fehlermeldung einfügen), aber Sie werden so ziemlich alle anderen überraschen.

+0

"Wenn Sie es jetzt ändern, wird zu viel vorhandener Code beschädigt." - Können Sie ein Beispiel geben? –

+0

@JanDvorak ja. Es gibt dort viel Code in der Wildnis, der mit dem berühmten 'jQuery-Code darin geschrieben wurde, bis es funktioniert'. Soweit wir wissen, könnte jemand Code haben, der OP ähnlich ist, und er benutzt das Werfen, um die anderen Zuhörer am Laufen zu hindern. –

+0

Ew. Das ist ein schrecklicher Weg, um dieses Ziel zu erreichen. Trotzdem - guter Punkt, danke. –

Verwandte Themen