2012-10-13 13 views
9

Wiedząc, że podczas node.js pracuje asynchronicznie, pisząc coś takiego:node.js: pętla zwrotna nie działa zgodnie z oczekiwaniami

function sleep() { 
    var stop = new Date().getTime(); 
    while(new Date().getTime < stop + 15000) { 
     ; 
    } 
} 

sleep(); 
console.log("done"); 

... nazwałbym sleep(), zablokować serwer dla czas trwania pętli while (15secs) i właśnie THEN print "done" na konsolę. O ile rozumiem, dzieje się tak dlatego, że Node.js zapewnia dostęp do głównego wątku tylko w języku JavaScript, a zatem to porwanie rzeczy powstrzymałoby dalszą realizację.

Rozumiem Rozwiązaniem tego problemu jest użycie wywołań zwrotnych:

function sleep(callback) { 
    var stop = new Date().getTime(); 
    while(new Date().getTime() < stop + 15000) { 
     ; 
    } 
    callback(); 
} 

sleep(function() { 
    console.log("done sleeping"); 
}); 

console.log("DONE"); 

więc myślałem, że to będzie drukować 'Gotowe' i po 15 sek. "done sleeping", ponieważ funkcja sleep() zostaje wywołana i przekazuje wskaźnik do funkcji wywołania zwrotnego. Gdy ta funkcja działa (pętla while), wykonywana jest ostatnia linia (print 'done'). Po 15 sekundach, gdy funkcja uśpienia() zostanie zakończona, wywołuje daną funkcję zwrotną, która następnie wypisuje "done sleeping".

Najwyraźniej zrozumiałem, że coś tutaj nie tak, ponieważ oba powyższe sposoby blokują. Czy ktoś może to wyjaśnić?

Dzięki z góry, Slagjoeyoco

Odpowiedz

13

Javascript i node.js są pojedyncze gwintowane, co oznacza proste while bloków; żadne żądania/zdarzenia nie mogą być przetwarzane, dopóki nie zostanie wykonany blok while. Oddzwanianie nie rozwiązuje magicznie tego problemu, po prostu pomagają przekazać niestandardowy kod do funkcji. Zamiast korzystania process.nextTick iteracji, co daje esentially takie same wyniki, ale pozostawia przestrzeń dla wniosków i zdarzeń do przetworzenia, jak również, to znaczy, że nie blokuje:

function doSleep(callback) { 
    var stop = new Date().getTime(); 

    process.nextTick(function() { 
     if(new Date().getTime() < stop + 15000) { 
      //Done, run callback 
      if(typeof callback == "function") { 
       callback(); 
      } 
     } else { 
      //Not done, keep looping 
      process.nextTick(arguments.callee); 
     } 
    }); 
} 

doSleep(function() { 
    console.log("done sleeping"); 
    console.log("DONE"); 
}); 
+0

Jesteś komplikuje się. Prosty setTimeout (callback, delay) powinien wystarczyć do wyprodukowania tego samego, co instrukcja asynchronicznie. –

+4

@ FabiánH.jr. chodzi o to, że OP może być zainteresowany zrozumieniem, dlaczego jego 'while' nie działa i jak" while "można pisać w sposób nieblokujący, co jest lepszą odpowiedzią niż" nie ma znaczenia twoja metoda nie działa, zrób to w inny sposób ". – Mahn

+0

Cóż, prawda, ogólnie rzecz biorąc, ogólnie rzecz biorąc, a teraz, gdy o tym wspomniałeś, było to bardzo wnikliwe w wewnętrznym procesie node.js –

2

oddzwaniania nie to samo, co asynchroniczność, oni są po prostu przydatne, gdy chcesz uzyskać ... wywołania zwrotnego ... od asynchronicznej operacji. W twoim przypadku metoda nadal jest wykonywana synchronicznie; Węzeł nie tylko w magiczny sposób wykrywa, że ​​istnieje oddzwanianie i długotrwała operacja, i że zwraca je z wyprzedzeniem.

Rozwiązaniem jest prawdziwe zamiast używać zajętej pętli w innym wątku.

9

Natychmiast dzwonisz pod numer sleep, a nowe bloki funkcyjne sleep. Powtarza on iterację, dopóki warunek nie zostanie spełniony. Należy użyć setTimeout() aby uniknąć blokowania:

setTimeout(function() { 
    console.log('done sleeping'); 
}, 15000); 
0

Jak już wspomniano, asynchroniczny egzekucja powinna zostać osiągnięta przez setTimeout() raczej niż chwilę, bo gdy zamarznie w jednej ramce „wykonanie”.

Wygląda na to, że w swoim przykładzie występuje błąd składni.

Ten działa prawidłowo: http://jsfiddle.net/6TP76/

Powiązane problemy