it-swarm.com.de

Wie kann ich warten? In Node.js (Javascript) muss ich eine Zeit lang pausieren

Ich entwickle ein Konsole-ähnliches Skript für persönliche Bedürfnisse. Ich muss in der Lage sein, längere Zeit anzuhalten, aber node.js hat aus meiner Recherche keine Möglichkeit, wie erforderlich anzuhalten. Es wird immer schwieriger, die Benutzerinformationen nach einiger Zeit zu lesen ... Ich habe Code dort draußen gesehen, aber ich glaube, dass sie anderen Code in sich haben müssen, damit sie funktionieren können:

setTimeout(function() {
}, 3000);

Ich brauche jedoch alles nach dieser Codezeile, um nach dem Zeitraum ausgeführt zu werden.

Zum Beispiel, 

//start-of-code
console.log('Welcome to My Console,');
some-wait-code-here-for-ten-seconds..........
console.log('Blah blah blah blah extra-blah');
//endcode. 

Ich habe auch Dinge wie gesehen

yield sleep(2000);

Aber node.js erkennt das nicht.

Wie kann ich diese verlängerte Pause erreichen?

221

Der beste Weg, dies zu tun, besteht darin, Ihren Code in mehrere Funktionen aufzuteilen:

function function1() {
    // stuff you want to happen right away
    console.log('Welcome to My Console,');
}

function function2() {
    // all the stuff you want to happen after that pause
    console.log('Blah blah blah blah extra-blah');
}

// call the first chunk of code right away
function1();

// call the rest of the code and have it execute after 3 seconds
setTimeout(function2, 3000);

Es ist der Lösung von JohnnyHK ähnlich, aber viel übersichtlicher und einfacher zu erweitern.

147

Eine neue Antwort auf eine alte Frage. Heute (Januar 2017) ist es viel einfacher. Sie können die new async/await-Syntax ..__ verwenden. Beispiel:

async function init(){
   console.log(1)
   await sleep(1000)
   console.log(2)
}
function sleep(ms){
    return new Promise(resolve=>{
        setTimeout(resolve,ms)
    })
}

Für die Verwendung von async/await ohne Installation und Plugins müssen Sie node-v7 oder node-v8 mit dem Flag --harmony verwenden.

Mehr Info:

186

Fügen Sie den Code, den Sie nach der Verzögerung ausführen möchten, im setTimeout Callback ein:

console.log('Welcome to My Console,');
setTimeout(function() {
    console.log('Blah blah blah blah extra-blah');
}, 3000);
127
JohnnyHK

Dies ist eine einfache Blockierungstechnik:

var waitTill = new Date(new Date().getTime() + seconds * 1000);
while(waitTill > new Date()){}

Es ist blockiert sofern nichts anderes in Ihrem Skript passiert (wie Callbacks). Aber da dies ein Konsolenskript ist, ist es vielleicht das, was Sie brauchen!

102
atlex2

Sie können diese www.npmjs.com/package/sleep verwenden.

var sleep = require('sleep');
sleep.sleep(10); // sleep for ten seconds
48
Aleksej

Einfache und elegante Schlaffunktion mit modernem Javascript

function sleep(millis) {
    return new Promise(resolve => setTimeout(resolve, millis));
}

Keine Abhängigkeiten, keine Callback-Hölle; das ist es :-)


Betrachten wir das in der Frage angegebene Beispiel: So schlafen wir zwischen zwei Konsolenprotokollen:

async function main() {
    console.log("Foo");
    await sleep(2000);
    console.log("Bar");
}

main();

Der "Nachteil" ist, dass Ihre Hauptfunktion jetzt auch async sein muss. Wenn Sie jedoch bereits modernen Javascript-Code schreiben, werden Sie wahrscheinlich (oder sollten es zumindest sein!) async/await überall in Ihrem Code verwenden. Alle modernen Browser heute unterstützen it.

Ein wenig Einblick in die sleep-Funktion für diejenigen, die nicht an async/await- und fette Pfeiloperatoren gewöhnt sind.

function sleep(millis) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () { resolve(); }, millis);
    });
}

Die Verwendung des Pfeilpfeil-Bedieners macht ihn jedoch noch kleiner (und eleganter).

46
Lucio Paiva

Die kürzeste Lösung ohne Abhängigkeiten:

await new Promise(done => setTimeout(done, 5000));
37
k06a

Diese Frage ist ziemlich alt, aber in letzter Zeit hat V8 Generatoren hinzugefügt, die die Anforderungen des OP erfüllen können. Generatoren sind im Allgemeinen am einfachsten für asynchrone Interaktionen mit Hilfe einer Bibliothek wie suspend oder gen-run zu verwenden.

Hier ein Beispiel mit suspend:

suspend(function* () {
    console.log('Welcome to My Console,');
    yield setTimeout(suspend.resume(), 10000); // 10 seconds pass..
    console.log('Blah blah blah blah extra-blah');
})();

Verwandte Lesung (durch schamlose Eigenwerbung): Was ist der große Deal mit Generatoren? .

33
jmar777

Auf Knoten 7.6.0 oder höher

Node unterstützt natives Warten:

const sleep = (waitTimeInMs) => new Promise(resolve => setTimeout(resolve, waitTimeInMs));

wenn Sie dann asynchrone Funktionen verwenden können:

await sleep(10000); // sleep for 10 seconds

oder:

sleep(10000).then(() => {
  // This will execute 10 seconds from now
});

Bei älteren Node-Versionen (ursprüngliche Antwort)

Ich wollte einen asynchronen Schlaf, der unter Windows und Linux funktionierte, ohne meine CPU mit einer langen Schleife zu belasten. Ich habe das Sleep-Paket ausprobiert, konnte es aber nicht auf meiner Windows-Box installieren. Ich endete mit:

https://www.npmjs.com/package/system-sleep

Um es zu installieren, geben Sie Folgendes ein:

npm install system-sleep

In Ihrem Code, 

var sleep = require('system-sleep');
sleep(10*1000); // sleep for 10 seconds

Klappt wunderbar.

24

Unter Linux/nodejs funktioniert das bei mir:

const spawnSync = required ('child_process'). spawnSync;

var sleep = spawnSync ('sleep', [1.5]);

Es blockiert, aber es ist keine beschäftigt Warteschleife.

Die von Ihnen angegebene Zeit ist in Sekunden, kann aber nur ein Bruchteil sein. Ich weiß nicht, ob andere Betriebssysteme einen ähnlichen Befehl haben.

14
Bart Verheijen

Ich habe vor kurzem eine einfachere Abstraktion mit dem Namen wait.for erstellt, um async-Funktionen im Synchronisationsmodus (basierend auf Knotenfasern) aufzurufen. Es gibt auch eine Version, die auf den kommenden ES6-Generatoren basiert.

https://github.com/luciotato/waitfor

Mit wait.for können Sie jede Standardknotenjs-async-Funktion wie eine Synchronisationsfunktion aufrufen, ohne die Ereignisschleife des Knotens zu blockieren. 

Sie können nacheinander Code programmieren, wenn Sie ihn benötigen. Dies ist (ich schätze) perfekt, um Ihre Skripts für den persönlichen Gebrauch zu vereinfachen.

bei Verwendung von wait.for lautet der Code:

require('waitfor')

..in a fiber..
//start-of-code
console.log('Welcome to My Console,');
wait.miliseconds(10*1000); //defined in waitfor/paralell-tests.js - DOES NOT BLOCK
console.log('Blah blah blah blah extra-blah');
//endcode. 

Jede async-Funktion kann auch in Sync mode ..__ aufgerufen werden. Überprüfen Sie die Beispiele.

13
Lucio M. Tato

Wenn Sie "Golf spielen" möchten, können Sie hier einige der anderen Antworten kürzer machen:

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

Aber meiner Meinung nach ist die ideale Antwort die Verwendung der Node-Bibliothek util und ihrer promisify-Funktion, die genau auf diese Art von Dingen ausgelegt ist (Versprechen-basierte Versionen von zuvor nicht-versprechen-basierten Sachen erstellen):

const util = require('util');
const sleep = util.promisify(setTimeout);

In beiden Fällen können Sie einfach pausieren, indem Sie mit await Ihre sleep-Funktion aufrufen:

await sleep(1000); // sleep for 1s/1000ms
11
machineghost

Da die JavaScript-Engine (v8) Code basierend auf der Ereignissequenz in der Ereigniswarteschlange ausführt, ist es nicht streng, dass Javascript die Ausführung nach einer bestimmten Zeit genau auslöst. Das heißt, wenn Sie einige Sekunden einstellen, um den Code später auszuführen, basiert der auslösende Code ausschließlich auf der Reihenfolge in der Ereigniswarteschlange. Das Auslösen der Ausführung von Code kann daher mehr als die angegebene Zeit dauern.

So folgt Node.js:

process.nextTick()

um den Code später auszuführen, setzen Sie stattdessen setTimeout (). Zum Beispiel,

process.nextTick(function(){
    console.log("This will be printed later");
});

Da ES6 Promises unterstützt, können wir sie ohne Hilfe von Drittanbietern verwenden.

const sleep = (seconds) => {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, (seconds * 1000));
    });
};

// We are not using `reject` anywhere, but it is good to
// stick to standard signature.

Dann benutze es so:

const waitThenDo(howLong, doWhat) => {
    return sleep(howLong).then(doWhat);
};

Beachten Sie, dass die doWhat-Funktion zum resolve-Callback innerhalb der new Promise(...) wird.

Beachten Sie auch, dass dies ASYNCHRONER Schlaf ist. Die Ereignisschleife wird nicht blockiert. Wenn Sie den Schlaf blockieren möchten, verwenden Sie diese Bibliothek, die mithilfe von C++ - Bindungen den Schlaf blockiert. (Zwar ist die Notwendigkeit eines blockierenden Ruhezustands in Node-ähnlichen Umgebungen eher selten.)

https://github.com/erikdubbelboer/node-sleep

2
treecoder

Dies ist ein moment.js-Modul, das auf dem Dirty-Blocking-Ansatz von @ atlex2 basiert. Verwenden Sie dies nur zum Testen von.

const moment = require('moment');

let sleep = (secondsToSleep = 1) => {
    let sleepUntill = moment().add(secondsToSleep, 'seconds');
    while(moment().isBefore(sleepUntill)) { /* block the process */ }
}

module.exports = sleep;
1
Boaz
let co = require('co');
const sleep = ms => new Promise(res => setTimeout(res, ms));

co(function*() {
    console.log('Welcome to My Console,');
    yield sleep(3000);
    console.log('Blah blah blah blah extra-blah');
});

Dieser Code oben ist der Nebeneffekt des Problems der asynchronen Callback-Hölle von Javascript. Dies ist meines Erachtens auch der Grund, warum Javascript im Backend eine nützliche Sprache ist. Tatsächlich ist dies meiner Meinung nach die aufregendste Verbesserung des modernen Javascript. Um zu verstehen, wie es funktioniert, muss die Funktionsweise des Generators vollständig verstanden werden. Das Schlüsselwort function, gefolgt von einem *, wird im modernen Javascript als Generatorfunktion bezeichnet. Das npm-Paket co lieferte eine Runner-Funktion zum Ausführen eines Generators.

Die Generatorfunktion bot im Wesentlichen eine Möglichkeit, die Ausführung einer Funktion mit dem Schlüsselwort yield anzuhalten. Gleichzeitig ermöglichte die Variable yield in einer Generatorfunktion den Informationsaustausch zwischen dem Generator und dem Aufrufer. Dies stellte einen Mechanismus für den Aufrufer bereit, um Daten aus einer promise eines asynchronen Aufrufs zu extrahieren und die aufgelösten Daten zurück an den Generator zu übergeben. Es macht effektiv einen asynchronen Aufruf synchron.

1
Elgs Qian Chen

einfach warten wir 5 Sekunden auf ein Ereignis (dies wird durch die an einem anderen Ort im Code auf true gesetzte done-Variable angezeigt) oder wenn das Zeitlimit abläuft, werden wir alle 100 ms überprüfen

    var timeout=5000; //will wait for 5 seconds or untildone
    var scope = this; //bind this to scope variable
    (function() {
        if (timeout<=0 || scope.done) //timeout expired or done
        {
            scope.callback();//some function to call after we are done
        }
        else
        {
            setTimeout(arguments.callee,100) //call itself again until done
            timeout -= 100;
        }
    })();
0
Stan Sokolov

Für manche Leute funktioniert die akzeptierte Antwort nicht, ich habe diese andere Antwort gefunden und funktioniert für mich: Wie kann ich einen Parameter an einen setTimeout () - Rückruf übergeben?

var hello = "Hello World";
setTimeout(alert, 1000, hello); 

'Hallo' ist der Parameter, der übergeben wird. Sie können alle Parameter nach Ablauf der Timeout-Zeit übergeben. Vielen Dank an @Fabio Phms für die Antwort.

0
Dazt

Schauen Sie sich readline-sync an ( https://www.npmjs.com/package/readline-sync )

Installation mit npm install readline-sync

var readlineSync = require('readline-sync');
while(true) {
  var input = readlineSync.question("What is your input?");
  if(input === 'exit') {
    process.exit();
  } else {
    console.log("Your input was " + input);
  }
}

Vielleicht nicht die beste Praxis, aber macht den Job für mich

0
MonoThreaded

Wenn Sie nur zu Testzwecken die aktuelle Thread-Ausführung aussetzen möchten, versuchen Sie Folgendes:

function longExecFunc(callback, count) {

    for (var j = 0; j < count; j++) {
        for (var i = 1; i < (1 << 30); i++) {
            var q = Math.sqrt(1 << 30);
        }
    }
    callback();
}
longExecFunc(() => { console.log('done!')}, 5); //5, 6 ... whatever. Higher -- longer
0
Ivan Talalaev