2014-04-10 2 views
8

strophe XMPP 및 jquery를 사용하여 애플리케이션의 이상한 동작이 발생한 후 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 
} 

두 개의 출력이 표시 될 것으로 예상되지만 두 번째 출력 : "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) 

우리는이 구현에 놀랐다.

순수 자바 스크립트에서는 모든 핸들러가 충돌하더라도 하나의 핸들러가 호출됩니다 (http://jsfiddle.net/bamthomas/kgS7A/2/).

누군가 JQuery 팀이 이전 처리기가 다운 된 경우에도 다음 처리기의 실행을 허용하지 않는 이유를 알고 있습니까? 예외가 붙잡히지 않는 이유는 무엇입니까?

왜 자바 스크립트 이벤트 처리기를 사용하지 않았습니까?

+0

"왜 jQuery가 예외를 catch하지 않습니까?" - 아무도 이것이 문제 일 수 있다고 생각하지 않기 때문일 가능성이 큽니다. 그들의 github repo에 끌어 오기 요청을 보내실 수 있습니다. –

+0

이벤트 처리기에서 throw 할 수있는 경우 예외를 잡는 것은 사용자의 책임입니다. 왜 '방아쇠'가 그렇게 할 것으로 기대합니까? – Tomalak

+0

jQuery가 예외를 잡아 내지 못한다는 발견만큼 유용 할 수 있습니다. 나는이 질문이 객관적으로 대답 될 수 있다고 생각하지 않습니다 ... –

답변

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 더 시도/캐치 없다.

그 방법은 yearsyears and years입니다.

원하는 경우에도 지금 변경하면 기존 코드가 너무 많이 손상됩니다. 지금 임의로 보이는 jQuery의 많은 것들이 다른 시간에 태어 났음을 기억하십시오.

물론 자신의 코드에서이 문제를 '고칠 수 있지만 (오류 메시지가있는 try/catch로 감싸기), 다른 모든 사람들은 놀라게 될 것입니다.

+0

"변경하면 기존 코드가 너무 많이 손상됩니다." - 예제를 제공해 줄 수 있습니까? –

+0

@JanDvorak 예. 그곳에는 '작동 할 때까지 유명한'throw jQuery '를 사용하여 코딩 된 많은 코드가 있습니다. 우리가 아는 한 누군가 OP와 비슷한 코드를 가지고있을 수 있으며 다른 리스너가 실행되는 것을 막기 위해 throwing을 사용하고 있습니다. –

+0

Ew. 그것은 그 목표를 달성하기위한 끔찍한 방법입니다. 아직 - 좋은 지적입니다, 고마워요. –

관련 문제