2012-04-07 6 views
5

Express와 함께 NodeJS로 작성된 응용 프로그램을 가지고 있으며 EventEmitter를 사용하여 방출 된 이벤트를 수신하여 기본 코드에 플러그인하는 플러그인으로 일종의 플러그인 아키텍처를 만들려고합니다.NodeJS는 이벤트 발생시 콜백 대기 완료

플러그인 기능이 비동기 요청 (이 경우에는 mongo에서 데이터 가져 오기)을하면 플러그인 코드가 완료되고 비동기 요청 전에 실행을 완료 할 원래 이미 터로 제어가 되돌아갑니다 플러그인 코드에서 완료됩니다.

예 :

메인 응용 프로그램 :

// We want to modify the request object in the plugin 
self.emit('plugin-listener', request); 

플러그인 :

// Plugin function listening to 'plugin-listener', 'request' is an arg 
console.log(request); 

// Call to DB (async) 
this.getFromMongo(some_data, function(response){ 
    // this may not get called until the plugin function has finished! 
} 

'getFromMongo'기능에서 주요 코드로 다시 콜백 함수를 피하기위한 나의 이유는이 0 또는 이벤트를 수신하는 많은 플러그인 일 수 있습니다. 이상적으로는 DB 물건

많은 감사 플러그인에 대한 EventEmitter를 사용

답변

3

에게 주요 응용 프로그램에 제어를 반환하기 전에 끝날 때까지 어떤 방법이 대기 할 당신이 청취자는 보장 할 수 없기 때문에/미들웨어 관리는 적합하지 않습니다 비동기 코드가 있으면 순차적으로 실행됩니다. 이것은 특히 이러한 리스너가 서로 또는 동일한 데이터와 상호 작용할 때 문제가됩니다.

그래서 미들웨어 기능을 연결/표현하는 것은 EventEmitter를 사용하는 대신 어레이에 저장되고 차례대로 실행됩니다. 그들은 각각 next()를 호출해야합니다. 기능을 수행 할 수 있습니다.

3

비동기 호출을 동기 동작과 함께 사용할 수 없습니다. 이벤트 방출기 (Klovadis가 지적한대로 이상적이지 않을 수도 있음)를 사용하려면 플러그인에서 원하는 코드가 포함 된 기본 앱의 기능을 트리거하는 이벤트를 내 보내야합니다. 실행을 '대기'합니다. 또한 모든 플러그인 호출이 MongoDB 콜백을 마칠 때까지 메인 코드가 실행되지 않도록 이벤트 호출을 기다리는 모든 플러그인 호출을 추적해야합니다.

var callList = ['pluginArgs1', 'pluginArgs2', 'pluginArgs3']; 
for (var i = 0; i < callList.length; i++){ 
    self.emit('plugin-listener', callList[i], i); 
} 

self.on('plugin-callback', function(i){ 
    callList.splice(i, 1); 
    if (callList.length < 1){ 
    //we're done, do something 
    } 
}); 
0

그것을 자신을 시도하지 않은하지만 당신은 이벤트 방출 된 코드에 의해 실행 기능의 배열로 이벤트의 데이터 객체에 속성을 사용할 수 :

리스너

foo.on('your-event', function(data) { 
    console.log(data); 
    // Then add the asynchronous code to a callbacks array 
    // in the event data object 
    data.callbacks.push(function(next) { 
    getFromMongo(some_data, function(err, result) { next(err) } 
    } 
}); 

self.emit('your-event', data); 
// listeners have modified data object, 
// some might have added callback to data.callbacks 
// (suppose you use async) 
async.series(data.callbacks); 
1

는 일부 이벤트에 대해 결정의 같은 종류를하였습니다 나는 언젠가 클라이언트에게 응답을 돌려주기 전에 기다려야 할 때가 있고 때로는 (HTTP 요청 컨텍스트에 없을 때) 기다릴 필요가 없다.

나를위한 가장 쉬운 방법은 콜백을 이벤트의 마지막 인수로 추가하는 것이 었습니다.내가 필요로하는 것에 대해

Stuff.on('do_some_stuff', function(data, data2, callback) { 
    // stuff to do 
    // ... 
    if (typeof callback === "function") return callback(err, result); 
}); 

내가 혼합 이벤트와 콜백 지저분한 될 수 있다는 것을 알고 있지만 잘 동작 : 이벤트 체크에

Stuff.emit('do_some_stuff', data, data2, callback); 

콜백이 있다면. 다른 해결책은 @redben에서 제안한 해결책입니다. 이벤트 끝 부분에 emit 함수를 추가하십시오. HTTP 컨텍스트에서 문제는 고유 키가 필요하므로 사용자별로 다른 작업을 수행 할 때 이벤트가 엉망이되지 않도록해야합니다.