2011-03-14 13 views
7

이것은 주로 언어에 구애받지 않는 질문입니다.두 개의 이벤트가 발생했을 때 코드 실행

두 개의 이벤트 (예 : 두 개의 IO 이벤트 또는 http 요청)가 완료되기를 기다리는 경우이를 처리하는 가장 좋은 패턴은 무엇입니까? 내가 생각할 수있는 한 가지는 다음과 같습니다 (의사 js 예제).

request1.onComplete = function() { 
    req1Completed = true; 
    eventsCompleted(); 
} 

request2.onComplete = function() { 
    req2Completed = true; 
    eventsCompleted(); 
} 

eventsCompleted = function() { 

    if (!req1Completed || !req2Completed) return; 
    // do stuff 

} 

이 방법이 가장 효과적인 패턴입니까? 아니면이 문제를 해결할 수있는보다 우아한 방법이 있습니까?

+6

이러한 이벤트가 특정 순서로 발생하기를 기대합니까? 그것은 솔루션에 큰 영향을 미칩니다. –

+0

아니요, 가능한 모든 주문 – Evert

답변

4

도 세부 사항으로 가기 전에, 여기 내 머리 위로 떨어져 람다 기능을 활용하여 깔끔한 뭔가 주문의 이점.

+0

이 솔루션은 기다리는 임의의 수의 이벤트가있는 경우 더 좋지만 이벤트가 발생하면 작동합니다. * 한 번 * 조금 위험합니다. –

+1

그건 다소 매끈합니다. 조금 미친, 그러나 매끄러운. –

+0

나쁜 해결책은 아닙니다. 이 부분은 저의 일부분이지만이 부분이 더러운 해결책이라고 생각합니다. :) – Evert

2

jQuery를 1.5 Deferreds 있습니다 http://api.jquery.com/category/deferred-object/

쉽게 몇 가지 이벤트가 트리거 된 경우에만 다시 전화를 설정할 수 있습니다. 이것은 분명 각각의 이벤트가 발생이 최대 한 번, 그리고하지 않는 것으로 가정

function makeCountdownCallback(count, callback) { 
    return function() { 
     if (--count == 0) 
      callback(); 
    }; 
} 

request1.onComplete = request2.onComplete = makeCountdownCallback(2, function() { 
    // do stuff 
}); 

:

+0

"지연됨"이 분명히 조사 할 항목입니다.그것은 당신이'afterAllOfThese (def1, def2, def2, function() {...})'의 라인을 따라 뭔가 여러 콜백을 추적 할 수 있도록 꽤 깔끔한 인터페이스를 만들 수 있습니다. ... 물론 jQuery가 이미 여러 이벤트. –

+0

여러 언어에 적용 할 수있는 일반적인 솔루션이 필요합니다. – Evert

1

시도 # 1 : 이벤트가 발생합니다 먼저 상대방의 옛 핸들러를 삭제됩니다

request1.onComplete = function() { 
    // register new handler for event2 here, overwriting the old one 
    request2.onComplete = function() { 
     // now they're both done 
    } 
} 

request2.onComplete = function() { 
    // register new handler for event1 here, overwriting the old one 
    request1.onComplete = function() { 
     // now they're both done 
    } 
} 

핸들러 중 대한과를 포함하는 새로운 하나를 할당 : 여기에 추가로 전역 변수를 필요로하지 않는 솔루션입니다 두 가지 사건이 모두 끝난 후에해야 할 일. 우리는 두 번째 처리기를 첫 번째 처리기의 처리기 (둘 중 어느 것이 든)에서 다시 할당하기 때문에 두 번째 처리기가 완료 될 때 완료된다는 것을 항상 알고 있습니다.

시도 # 2 : 사용자가 모두 스크롤 및 클릭 할 때까지

function onBoth(fn) { 
    var last, done = false; 
    return function(e) { 
     if (last && last !== e.type && !done) { 
      fn(); // done 
      done = true; 
     } 
     last = e.type; 
    } 
} 

예를 들어,이 "완료"경고하지 않습니다 : 다음은 각 이벤트 유형이 다른 경우 작동 뭔가의

var both = onBoth(function() { 
    alert("done") 
}); 

document.addEventListener("scroll", both, false); 
document.addEventListener("click", both, false); 

시도 # 3 :

: 이전의 시도는 비슷한 이벤트에 대한 작업을 수정할 수 있습니다 이와 같이 표기

는 ... :

var check = onBoth(function() { 
    alert("done") 
}); 

request1.onComplete = function() { 
    check(arguments.callee); 
} 

request2.onComplete = function() { 
    check(arguments.callee); 
} 

기본적으로,이 두 가지 콜백 다시 가장 최근에 실행 된 호에 대한 참조를 저장함으로써 실행되는 것을 확인한다. 사용법은 조금 복잡하지만 작업이 완료됩니다 (즉, 각 이벤트가 두 번 이상 실행될 경우 계속 작동합니다). 그것을 할 수

+0

'request1'과'request2'는 꽤 글로벌하게 보입니다. –

+0

@Matti - 물론 그렇습니다. 분명히 각 처리기가 완료되었음을 나타 내기 위해 추가 전역 플래그가 필요하지 않습니다. –

관련 문제