2012-10-13 12 views
9

Arbeits Zu wissen, dass während Node.js asynchron arbeitet, so etwas wie dieses zu schreiben:node.js: while-Schleife Rückruf nicht wie erwartet

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

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

... würde den Schlaf() aufrufen, blockieren den Server für die Dauer der While-Schleife (15 Sekunden) und DANN drücke "Done" auf die Konsole. Soweit ich das verstehe, liegt das daran, dass Node.js JavaScript nur den Zugriff auf den Hauptthread gewährt, und daher würde diese Entführung die weitere Ausführung stoppen.

So verstehe ich die Lösung dieses Problems ist Rückrufe zu verwenden:

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

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

console.log("DONE"); 

Also dachte ich, das wäre ‚DONE‘ und nach 15 Sekunden drucken. 'done sleeping', da die Funktion sleep() aufgerufen wird und ein Zeiger auf eine Callback-Funktion übergeben wird. Während diese Funktion arbeitet (die while-Schleife), wird die letzte Zeile ausgeführt (print 'done'). Nach 15 Sekunden, wenn die Funktion sleep() beendet ist, ruft sie die angegebene Callback-Funktion auf, die dann 'done sleeping' ausgibt.

Anscheinend habe ich hier etwas falsch verstanden, weil beide der oben genannten Möglichkeiten blockieren. Kann jemand bitte klären?

Vielen Dank im Voraus, Slagjoeyoco

Antwort

13

Javascript und node.js single threaded ist, die ein einfachen while Blöcke bedeuten; keine Anfragen/Ereignisse können bearbeitet werden, bis der while Block fertig ist. Callbacks lösen dieses Problem nicht auf magische Weise, sie helfen nur dabei, benutzerdefinierten Code an eine Funktion zu übergeben. Stattdessen iterieren process.nextTick verwenden, die Sie esentially die gleichen Ergebnisse liefern, sondern lässt Raum für Anfragen und Ereignisse als auch verarbeitet werden, dh nicht blockiert es nicht:

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

Sie sind selbst zu verkomplizieren. Ein einfaches setTimeout (Callback, Delay) sollte ausreichen, um dasselbe wie asynchron zu erzeugen. –

+4

@ FabiánH.jr. Der Punkt ist OP könnte daran interessiert sein, zu verstehen, warum sein 'while' nicht funktioniert und wie ein' while' auf nicht-blockierende Weise geschrieben werden kann, was imho irgendwie eine bessere Antwort ist als "es spielt keine Rolle für Ihre Methode funktioniert nicht, mach es stattdessen anders. – Mahn

+0

Nun, wahr, große Antwort insgesamt und jetzt, dass Sie es erwähnen, war es ziemlich aufschlussreich in den inneren Prozess von node.js –

2

Rückrufe sind nicht dasselbe wie Asynchronität, sie sind nur nützlich, wenn Sie einen ... Rückruf erhalten möchten ... von einem asynchronen Betrieb. In Ihrem Fall wird die Methode weiterhin synchron ausgeführt. Node erkennt nicht nur auf magische Weise, dass es einen Callback und eine lang andauernde Operation gibt, und lässt sie vorzeitig zurückkehren.

Die echte Lösung ist zu verwenden setTimeout anstelle einer Busy-Schleife in einem anderen Thread.

9

Sie rufen sofort sleep und die neuen sleep Funktionsblöcke. Es wiederholt so lange, bis die Bedingung erfüllt ist. Sie sollten setTimeout() verwenden Blockierung zu vermeiden:

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

Wie bereits erwähnt, soll die asynchrone Ausführung von setTimeout erreicht werden() statt, während, denn während in einer „Ausführung Rahmen“ einfriert.

Auch scheint es, dass Sie Syntaxfehler in Ihrem Beispiel haben.

arbeitet Diese fein: http://jsfiddle.net/6TP76/

Verwandte Themen