2017-07-04 3 views
2

Ich schreibe eine node.js Konsolenanwendung. Ich habe zwei setTimeout-Funktionen wie folgt.Pipelining setTimeout in node.js

setTimeout(function(){ 
    process.stdout.write('\n\nJokes Apart !!!\n\n'); 
}, 2000); 

setTimeout(function(){ 
    process.stdout.write('\n\nLet\'s play a game !!!\n\n'); 
}, 1000); 

Was ich eigentlich beabsichtige ist, sollte die erste Nachricht nach 2 Sekunden kommen. Danach sollte die zweite Nachricht nach 1 Sekunde erscheinen. Aber was passiert ist, die zweite Nachricht erscheint nach 1 Sekunde und dann erscheint die erste Nachricht. Beide Funktionen werden gleichzeitig aufgerufen, da sie asynchron sind. Gibt es eine Möglichkeit, sie zu pipen?

Antwort

2

setTimout() blockiert nicht in Javascript. Also, was Sie getan haben, ist, dass Sie zwei Timer für die Zukunft planen. Man läuft 1 Sekunde von jetzt. Der andere läuft zwei Sekunden von jetzt. So erhalten Sie das Verhalten, das Sie beobachtet haben.

Sie können entweder planen, dass der erste in 2 Sekunden abläuft und dann für 1 Sekunde danach für 3 Sekunden.

setTimeout(function(){ 
    process.stdout.write('\n\nJokes Apart !!!\n\n'); 
}, 2000); 

// schedule this one to be 3 seconds from now, which will be 1 second after the prior one 
// since that one fired in 2 seconds 
setTimeout(function(){ 
    process.stdout.write('\n\nLet\'s play a game !!!\n\n'); 
}, 3000); 

Oder Sie können die erste von nun laufen 2 Sekunden planen und dann in diesem Rückruf planen Sie dann die nächste 1 Sekunde aus, wenn die ersten ein Feuer laufen.

setTimeout(function(){ 
    process.stdout.write('\n\nJokes Apart !!!\n\n'); 
     // when the first timer fires, set a new timer to run the second 
     // part one second from when the first one fired 
     setTimeout(function(){ 
      process.stdout.write('\n\nLet\'s play a game !!!\n\n'); 
     }, 1000); 
}, 2000); 

Diese nicht blockierende Eigenschaft gibt Javascript das asynchrone Verhalten. Wenn Sie den ersten setTimeout() aufrufen, stoppt der Javascript-Interpreter nicht nur und wartet darauf, dass der Timer ausgelöst wird. Stattdessen plant es, dass der Timer irgendwann in der Zukunft ausgeführt wird, und dann führt er den Rest Ihres Javascript weiter aus. In Ihrem Code ist die nächste Zeile des Codes eine andere setTimeout(), so dass es sofort diesen Timer auch plant. Da sie beide zur selben Zeit geplant waren, ist es sinnvoll, dass der für 2 Sekunden geplante Termin nach dem für 1 Sekunde geplanten Termin liegt.

So haben Sie am Ende zwei Möglichkeiten. Sie können die Uhrzeit entweder beim zweiten Mal ändern, damit sie ausgelöst wird, wenn Sie möchten, dass sie ausgelöst wird (vorausgesetzt, dass der Code für beide Timer im Grunde zur gleichen Zeit läuft) oder Sie können ändern, wenn Sie den zweiten Timer bis planen nachdem der erste Timer ausgelöst hat.

1

Um zu verstehen, was passiert, sollten Sie zuerst die JS-Ereignisschleife und ihre nicht blockierende Natur verstehen. Sie können hier darüber lesen: https://blog.risingstack.com/node-js-at-scale-understanding-node-js-event-loop/, oder wenn Sie Videoform bevorzugen, ist dies eine große Diskussion: https://youtu.be/8aGhZQkoFbQ

Auf den Punkt gebracht, geht der Motor durch den Code - wenn er trifft auf den ersten setTimeout, es Pläne es (für 2 Sekunden später) und geht weiter. Es sieht dann das zweite setTimeout und plant es auch. Wenn eine Sekunde verstrichen ist, wird der Rückruf von der zweiten setTimeout ausgelöst und ausgeführt, und nur eine Sekunde später wird der Rückruf von der ersten ausgelöst. Deshalb sehen Sie sie in dieser Reihenfolge.

Jetzt ist es zu Fixierung - alles, was Sie tun müssen, ist nur Nest sie:

setTimeout(function(){ 
    process.stdout.write('\n\nJokes Apart !!!\n\n'); 

    setTimeout(function(){ 
     process.stdout.write('\n\nLet\'s play a game !!!\n\n'); 
    }, 1000); 
}, 2000); 

Dies ist die zweite setTimeout verursacht nur geplant werden, wenn der Rückruf vom ersten ausgeführt wird.