2011-06-22 16 views
64

mam kod jak poniżej:Jak zapobiec uruchamianiu Node.js podczas oczekiwania na oddzwonienie?

var client = new mysql.Client(options); 
console.log('Icanhasclient'); 

client.connect(function (err) { 
    console.log('jannn'); 
    active_db = client; 
    console.log(err); 
    console.log('hest'); 

    if (callback) { 
    if (err) { 
     callback(err, null); 
    } 

    callback(null, active_db); 
    } 
}); 

Moim problemem jest to, że węzeł kończy natychmiast po uruchomieniu go. Wypisuje "Icanhasclient", ale żaden z console.log wewnątrz callback nie jest wywoływany.

(mysql w tym przykładzie jest node-mysql.

Czy istnieje coś, co można zrobić, aby node.js czekać na wywołanie zwrotne, aby zakończyć przed wyjściem?

+1

co masz na myśli, aby zapobiec wyjściu? Nodejs nie wychodzi, dopóki wszystkie połączenia zwrotne nie zostaną zakończone. Jest to proces z jednym wątkiem. – neebz

+2

@nEEbz: Jeśli tak, to dlaczego mój skrypt jest zamykany bez wykonywania wywołania zwrotnego? – mikl

+0

To jest problem z połączeniem z bazą danych; Nie jestem pewien, dlaczego nie uruchamia wywołania zwrotnego. Czy daje jakiś błąd? – neebz

Odpowiedz

39

oddzwaniania jest Nie kolejce

Node biegnie aż wszystkie zdarzenia kolejek pusty a. zwrotna jest dodany do kolejkiprzypadku gdy połączenia takie jak

emmiter1.on('this_event',callback). 

został wykonany. To wywołanie jest częścią kodu napisanego przez programistę modułu.

Jeśli moduł jest portem szybkim z wersji synchronicznej/blokującej, może się to nie zdarzyć, dopóki część operacji nie zostanie zakończona, a wszystkie kolejki mogą się opróżnić, zanim to nastąpi, pozwalając węzłowi na cichą pracę.

To podstępne bug, że jest jeden, że deweloper moduł może nie działać w trakcie rozwoju, jako że występują rzadziej w ruchliwych układów z wieloma kolejek jak to będzie rzadko wszystkie z nich mają być puste w krytycznym momencie.

Ewentualnym detektorem usterek/błędów dla użytkownika jest wstawienie specjalnego zdarzenia licznika czasu przed wywołaniem funkcji podejrzanej.

+0

"może się to nie zdarzyć aż do zakończenia części operacji" - Czy możesz to wyjaśnić? może zamknąć się, gdy fragment kodu jest nadal uruchomiony, zanim będzie mógł dodać wywołanie zwrotne do kolejki zdarzeń? –

+0

Domyślam się, że oznacza to, że jeśli biblioteka dokonała konwersji kodu, który był synchroniczny z nową wersją asynchroniczną, możliwe jest, że twórcy bibliotek zapomnieli ustawiać w kolejce wywołania zwrotne, a kolejki zdarzeń są opróżniane gdzieś w trakcie wykonywania, kończąc na nieobsłużonych wywołaniach zwrotnych –

0

Zerknąłem na bibliotekę felixge/node-mysql i nie widziałem odwołania do polecenia client.connect w interfejsie API. Czy to jest faktyczne połączenie, które próbujesz wykonać (nie starając się być tutaj dziwacznym)? Niezależnie od tego, IMHO musisz zastanowić się nad tym, jak zaprojektowana jest Javascript, ponieważ używa paradygmatu programowania innego niż większość popularnych języków.

Pierwszy problem, jaki widzę w twoim kodzie, to że nie zdefiniowałeś wywołania zwrotnego, więc tak naprawdę nie istnieje. Zakładam, że console.log (callback) jest niezdefiniowany. Z Twojego kodu funkcja anonimowa to "oddzwanianie" dla funkcji client.connect. Musisz zdefiniować to, co nazywasz "oddzwanianiem" w wyższym zakresie. Na przykład zdefiniuję funkcję myCallback istniejącą w zakresie wyższym niż anonimowa funkcja client.connect. Przydatne może być wyszukiwanie Javacscript variable scope.

var myCallback(err, response) { 
     if (err) { 
     console.log('err:%s',err); 
     } else { 
     console.log('response:%s',response); 
     } 
    } 

    client.connect(err, function(response) { 
     // this anonymous function is the callback to client.connect, the var 
     // 'callback' would be undefined. 
     if (err) { 
     myCallback(err); 
     return; // Explicit call to return, else the lines below would run. 
     } 
     myCallback(null, response); 
    }); 

Po drugie, jeśli nie wywołasz jawnie zwrotu w JavaScript, funkcja będzie dalej przetwarzać. Zostałem ugryziony przez to myself. W końcu Javascript uruchamia pętlę event-driven, co oznacza, że ​​nigdy nie będzie czekać na zwracanie przez funkcję wartości, dlatego wszystkie te wywołania zwrotne są wykonywane w pierwszej kolejności. Możesz zmusić Javascript, aby zachowywał się inaczej, na przykład używając pętli while, dopóki warunek nie jest prawdziwy. Zobacz bibliotekę "asynchroniczną" według caolan, aby poznać różne strategie manipulowania pętlą zdarzeń. Główną wadą nadużywania tych metod jest faktyczne marnowanie cykli/blokad procesora, kiedy prawdopodobnie powinieneś używać więcej wywołań zwrotnych i po prostu przemyśleć działanie swoich programów.

30

Możesz po prostu wydać setTimeout lub powtarzalny limit czasu za pomocą setInterval.

Jeśli chcesz sprawdzić warunki wyjścia, można również zrobić warunkową timeout:

(function wait() { 
    if (!SOME_EXIT_CONDITION) setTimeout(wait, 1000); 
})(); 

Umieścić to na końcu kodu i konsola będzie tylko czekać ... i czekać ... do momentu, aż to się skończy.

+3

Jest to dobre obejście, ale nie ładne rozwiązanie (co nie jest twoją winą, ale węzłem). – peterh

3

Moim rozwiązaniem było utworzenie instancji EventEmitter i odsłuchanie niestandardowego zdarzenia.

var eventEmitter = new process.EventEmitter(); 

następnie zadzwoniłem eventEmitter.emit z zwrotnego async:

client.connect(function (err) { 
    eventEmitter.emit('myevent', {something: "Bla"}) 
}); 

Ostatnią rzeczą w moim skrypcie był eventEmitter.on:

eventEmitter.on('myevent', function(myResult){ 
    // I needed the result to be written to stdout so that the calling process could get it 
    process.stdout.write(JSON.stringify(myResult)); 
}); 

Węzeł będzie wtedy poczekać, aż obsługi zdarzeń kończy uruchomiony .

+0

Otrzymuję komunikat "process.EventEmitter nie jest konstruktorem." Co byś zasugerował? –

+0

L ook up jak stworzyć EventEmitter. https://coligo.io/nodejs-event-emitter/ wydaje się dobrym zasobem. Możliwe, że różne wersje węzła zmieniły sposób jego tworzenia. – you786

+0

'EventEmitter' klasa jest definiowana przez moduł' events'. Aby utworzyć nowy emiter: 'const EventEmitter = require ('events'); var eventEmitter = new EventEmitter() '. – CedX

Powiązane problemy