2012-04-07 15 views
5

Mam i aplikacji napisanych w NodeJS z Express i próbuję użyć EventEmitter do stworzenia architektury wtyczki z wtyczkami do głównego kodu, słuchając emitowanych zdarzeń.NodeJS czekać na oddzwonienie, aby zakończyć na wydarzenie emitować

Mój problem pojawia się, gdy funkcja wtyczki wysyła żądanie asynchroniczne (w tym przypadku pobiera dane z mongo), co powoduje zakończenie kodu wtyczki i powrót do oryginalnego nadajnika, który zakończy wykonywanie, przed żądaniem asynchronicznym w zakończeniu kodu wtyczki.

Np

główna App:

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

Plugin:

// 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! 
} 

Mój powód do unikania funkcję zwrotną z powrotem do głównego kodu z funkcja 'getFromMongo' jest to, że może być 0 lub wiele wtyczek nasłuchujących zdarzenia. Idealnie chcę jakiś sposób, aby czekać na rzeczy DB zakończyć przed powrotem kontrolę do głównej aplikacji

Dziękujemy

Odpowiedz

3

Używanie EventEmitter dla wtyczki/zarządzanie middleware nie jest idealna, ponieważ nie można zagwarantować, że słuchacze są wykonywane sekwencyjnie, jeśli mają kod asynchroniczny. Jest to szczególnie problematyczne, gdy słuchacze współdziałają ze sobą lub z tymi samymi danymi.

To dlatego funkcje łączenia/wyrażania oprogramowania pośredniego są przechowywane w tablicy i wykonywane jeden po drugim, zamiast korzystania z EventEmitter; Każdy z nich musi wywołać next(); działają, gdy są gotowe, wykonując swoje zadanie.

3

Nie można łączyć wywołań asynchronicznych z synchronicznym zachowaniem. Jeśli masz zamiar trzymać się emitera zdarzeń (co może nie być idealne dla ciebie, jak wskazał Klovadis), musisz mieć wtyczkę emitującą zdarzenie, które uruchamia funkcję w głównej aplikacji, która zawiera kod, który chcesz "czekać", aby wykonać. Trzeba też z kolei śledzić wszystkie wykonane przez ciebie wywołania wtyczek, na które czekasz na wywołania zdarzeń, aby Twój główny kod nie działał, dopóki wszystkie wywołania wtyczek nie zakończą swoich wywołań 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

nie próbował go samodzielnie, ale można użyć właściwości w obiekcie danych imprezy jako tablica funkcji do wykonania przez kod, który emitowany wydarzenia:

Listeners

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) } 
    } 
}); 

Emiter

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

Podjął taką samą decyzję dotyczącą wydarzeń, które Czasem muszę poczekać, zanim zwrócę odpowiedź do klienta, a czasami nie (jeśli nie w kontekście żądania HTTP).

Najprostszym sposobem dla mnie było dodanie wywołania zwrotnego jako ostatniego argumentu zdarzenia.

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

W kontroli zdarzeń, jeżeli jest zwrotna:

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

wiem, że mieszanie zdarzenia i wywołania zwrotne może być brudny, ale to praca grzywny za to, czego potrzebuję. Drugim rozwiązaniem, które widzę, jest propozycja @redben: dodaj funkcję emitującą na końcu zdarzenia. Problem występujący w kontekście HTTP polega na tym, że potrzebujesz unikatowych kluczy, dzięki czemu Twoje wydarzenia nie będą zepsuć, jeśli będą robiły różne rzeczy na użytkownika.

Powiązane problemy