2012-03-30 10 views
9

Mam aplikacji węzeł, który nie aplikacja internetowa - to uzupełnia szereg zadań asynchronicznych przed powrotem 1. Bezpośrednio przed powrotem, wyniki programu są wypisywane na konsoli.Jak napisać funkcję node.js, która czeka na uruchomienie zdarzenia przed "zwróceniem"?

Jak mogę sprawdzić, czy wszystkie asynchroniczna praca jest zakończona przed powrotem? Udało mi się osiągnąć coś podobnego w aplikacji internetowej, upewniając się, że wszystkie zadania zostały zakończone przed wywołaniem res.end(), ale nie mam żadnego odpowiednika dla końcowego "zdarzenia", aby zadzwonić przed zezwoleniem na powrót skryptu.

Zobacz poniżej dla mojego (łamany) Funkcja Obecnie próbuje czekać aż callstack jest pusty. Właśnie odkryłem, że jest to rodzaj bezsensownego podejścia, ponieważ węzeł czeka na zakończenie procesu, zanim przejdzie do dowolnej asynchronicznej funkcji wywoływanej w processObjWithRef.

function processHub(hubFileContents){ 
    var callStack = []; 
    var myNewObj = {}; 
    processObjWithRef(samplePayload, myNewObj, callStack); 
    while(callStack.length>0){ 
     //do nothing 
    } 
    return 1 
} 

Uwaga: Próbowałem wiele razy wcześniej, aby osiągnąć ten rodzaj zachowań z bibliotek takich jak async (patrz moja powiązane pytanie na How can I make this call to request in nodejs synchronous?), więc proszę wziąć odpowiedź i komentarze tam pod uwagę przed sugerując żadnych odpowiedzi na podstawie " po prostu użyj asynch ".

+1

„Jak mogę sprawdzić, czy wszystkie asynchroniczna praca jest zakończona przed powrotem ? " Jest bezsensowne pytanie - kontrola nie jest zwracana do powłoki, dopóki wszystkie zadania asynchroniczne nie zostaną zakończone, więc pozostawienie wyjścia konsoli do momentu zakończenia ostatniej asynchronicznej funkcji naprawiło mój problem. Dziękuję wszystkim za przesłanie odpowiedzi. – Trindaz

Odpowiedz

5

Problem dotyczy projektu funkcji. Użytkownik chce zwrócić wynik synchroniczny z listy zadań, które są wykonywane asynchronicznie.

Powinieneś zaimplementować swoją funkcję z dodatkowym parametrem, który będzie zwrotem, w którym możesz umieścić wynik (w tym przypadku 1), aby jakiś konsument mógł coś z nim zrobić.

Również trzeba mieć parametr wywołania zwrotnego w swojej wewnętrznej funkcji, w przeciwnym razie nie będą wiedzieć, kiedy kończy. Jeśli ta ostatnia rzecz nie jest możliwa, to powinieneś zrobić coś w rodzaju pollingu (używając setInterval), aby przetestować, kiedy tablica callStack jest wypełniona.

Pamiętaj, że w JavaScript nigdy nie powinno się nigdy robić zajęty czekać. To zablokuje twój program całkowicie, ponieważ działa na jednym procesie.

1

Problem polega na tym, że plik node.js jest jednowątkowy, co oznacza, że ​​jeśli uruchomiona jest jedna funkcja, nic innego nie działa (pętla zdarzeń), dopóki ta funkcja nie powróci. Nie można więc zablokować funkcji, aby była zwracana po wykonaniu operacji asynchronicznej.

Można na przykład ustawić zmienną licznika, która zlicza uruchomione zadania asynchroniczne i dekrementować licznik za pomocą funkcji wywołania zwrotnego (która zostanie wywołana po zakończeniu zadania) z kodu asynchronicznego.

5

Nie można czekać na asynchronicznego zdarzenia przed powrotem - to definicja asynchroniczne! Próba wymuszenia na Node tego stylu programowania spowoduje tylko ból. Naiwnym przykładem może być okresowe sprawdzanie, czy callstack jest puste.

var callstack = [...]; 

function processHub(contents) { 
    doSomethingAsync(..., callstack); 
} 

// check every second to see if callstack is empty 
var interval = setInterval(function() { 
    if (callstack.length == 0) { 
    clearInterval(interval); 
    doSomething() 
    } 
}, 1000); 

Zamiast tego, zwykłym sposobem robienia rzeczy asynchronicznych w węźle jest zaimplementowanie wywołania zwrotnego do funkcji.

function processHub(hubFileContents, callback){ 
    var callStack = []; 
    var myNewObj = {}; 
    processObjWithRef(samplePayload, myNewObj, callStack, function() { 
    if (callStack.length == 0) { 
     callback(some_results); 
    } 
    }); 
} 

Jeśli naprawdę chcesz coś zwrócić, sprawdź promises; mają gwarancję, że wydadzą wydarzenie albo natychmiast, albo w pewnym momencie w przyszłości, kiedy zostaną rozwiązane.

function processHub(hubFileContents){ 
    var callStack = []; 
    var myNewObj = {}; 
    var promise = new Promise(); 

    // assuming processObjWithRef takes a callback 
    processObjWithRef(samplePayload, myNewObj, callStack, function() { 
    if (callStack.length == 0) { 
     promise.resolve(some_results); 
    } 
    }); 

    return promise; 
} 

processHubPromise = processHub(...); 
processHubPromise.then(function(result) { 
    // do something with 'result' when complete 
}); 
0

Musisz zacząć projektować i myśleć asynchronicznie, co może zająć trochę czasu, zanim się przyzwyczaicie. Jest to prosty przykład tego, jak poradzić sobie z "wywoływaniem" po wywołaniu funkcji.

function doStuff(param, cb) { 
    //do something 
    var newData = param; 
    //"return" 
    cb(newData); 
} 

doStuff({some:data}, function(myNewData) { 
    //you're done with doStuff in here 
}); 

Istnieje również wiele przydatnych funkcji użytkowych w bibliotece async dostępny na KMP.

3

deasync jest zaprojektowany, aby dokładnie rozwiązać problem. Wystarczy zastąpić

while(callStack.length>0){ 
    //do nothing 
} 

z

require('deasync').loopWhile(function(){return callStack.length>0;}); 
1

node.js biegnie na jednym gwintowanym pętli zdarzeń i wykorzystuje asynchronicznych wywołań dla robią różne rzeczy, na przykład operacji I/O.

jeśli trzeba czekać na wielu asynchronicznych operacji do końca przed wykonaniem dodatkowego kodu można spróbować użyć asynchroniczny -

Node.js Async Tutorial

Powiązane problemy