Hoe kan ik wachten in Node.js (JavaScript)? Ik moet een tijdje pauzeren

Ik ontwikkel een consolescript voor persoonlijke behoeften. Ik moet een langere tijd kunnen pauzeren, maar uit mijn onderzoek kan Node.js niet stoppen zoals vereist. Het wordt na verloop van tijd moeilijk om de informatie van gebruikers te lezen… Ik heb wat code gezien, maar ik geloof dat ze andere code in zich moeten hebben om te kunnen werken, zoals:

   setTimeout(function() {
    }, 3000);

Ik heb echter alles na deze regel code nodig om na verloop van tijd uit te voeren.

Bijvoorbeeld

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

Ik heb ook dingen gezien als

   yield sleep(2000);

Maar Node.js herkent dit niet.

Hoe kan ik deze verlengde pauze bereiken?


Antwoord 1, autoriteit 100%

Update januari 2021: je kunt het zelfs doen in de Node REPL interactive met --experimental-repl-awaitflag

$ node --experimental-repl-await
> const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
> await delay(1000) /// waiting 1 second.

Een nieuw antwoord op een oude vraag. Vandaag ( jan 2017juni 2019) is het veel makkelijker. U kunt de nieuwe async/awaitsyntaxis.
Bijvoorbeeld:

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

Voor het gebruik van async/awaituit de doos zonder installatie en plug-ins, moet je node-v7 of node-v8 gebruiken, met behulp van de --harmonyvlag.

Update juni 2019:door de nieuwste versies van NodeJS te gebruiken, kunt u deze direct gebruiken. U hoeft geen opdrachtregelargumenten op te geven. Zelfs Google Chrome ondersteunt het tegenwoordig.

Update mei 2020:
Binnenkort kunt u de syntaxis awaitgebruiken buiten een async-functie. Op het hoogste niveau zoals in dit voorbeeld

await sleep(1000)
function sleep(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
} 

Het voorstel bevindt zich in fase 3.
Je kunt het vandaag nog gebruiken door webpack 5 (alpha) te gebruiken,

Meer info:


Antwoord 2, autoriteit 66%

De kortste oplossing zonder enige afhankelijkheden:

await new Promise(resolve => setTimeout(resolve, 5000));

Antwoord 3, autoriteit 38%

De beste manier om dit te doen, is door uw code op te splitsen in meerdere functies, zoals deze:

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);

Het lijkt op de oplossing van JohnnyHK, maar is veel netter en gemakkelijker uit te breiden.


Antwoord 4, autoriteit 26%

Dit is een eenvoudige blokkeringstechniek:

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

Het blokkeertvoor zover er niets anders in je script gebeurt (zoals callbacks). Maar aangezien dit een consolescript is, is het misschien wat je nodig hebt!


Antwoord 5, autoriteit 24%

Plaats de code die u wilt uitvoeren na de vertraging binnen de setTimeoutcallback:

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

Antwoord 6, autoriteit 13%

Op Node 7.6.0 of hoger

Node ondersteunt native wachten:

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

Dan als u ASYNC-functies kunt gebruiken:

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

of:

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

op oudere knooppunten (origineel antwoord)

Ik wilde een asynchrone slaap die werkte in Windows & AMP; Linux, zonder mijn CPU te zwaaien met een lange tijd. Ik heb het slaappakket geprobeerd, maar het zou niet installeren op mijn Windows-doos. Ik eindigde met het gebruik van:

https://www.npmjs.com/package/system-sleep < / p>

Typ:

npm install system-sleep

in uw code,

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

werkt als een charme.


Antwoord 7, Autoriteit 10%

Eenvoudige en elegante slaapfunctie met behulp van moderne Javascript

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

Geen afhankelijkheden, geen callback-hel; Dat is het: -)


Gezien het voorbeeld in de vraag, is dit hoe we zouden slapen tussen twee console-logs:

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

Het “nadeel” is dat je hoofdfunctie nu ook asyncmoet zijn. Maar aangezien je al moderne Javascript-code schrijft, gebruik je waarschijnlijk (of zou je dat in ieder geval moeten doen!) async/awaitin je hele code, dus dit is echt niet een probleem. Alle moderne browsers ondersteunenhet.

Om een beetje inzicht te geven in de sleep-functie voor degenen die niet gewend zijn aan async/awaiten fat arrow-operators, dit is de uitgebreide manier om het te schrijven:

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

Het gebruik van de fat arrow-operator maakt het echter nog kleiner (en eleganter).


Antwoord 8, autoriteit 8%

U kunt deze www.npmjs.com/package/sleep

gebruiken

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

Antwoord 9, autoriteit 5%

Deze vraag is vrij oud, maar onlangs heeft V8 generatoren toegevoegd die kunnen bereiken wat de OP heeft gevraagd. Generatoren zijn over het algemeen het gemakkelijkst te gebruiken voor asynchrone interacties met behulp van een bibliotheek zoals suspendof gen-run.

Hier is een voorbeeld van het gebruik van opschorten:

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

Gerelateerde literatuur (bij wijze van schaamteloze zelfpromotie): Wat is het probleem met generatoren?.


Antwoord 10, autoriteit 5%

Als u golf wilt “coderen”, kunt u hier een kortere versie van enkele van de andere antwoorden maken:

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

Maar naar mijn mening is het ideale antwoord om de util-bibliotheek van Node en de functie promisifyte gebruiken, die voor precies dit soort dingen is ontworpen (op beloften gebaseerd versies van eerder bestaande niet-belofte-gebaseerde dingen):

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

In beide gevallen kunt u eenvoudig pauzeren door awaitte gebruiken om uw sleep-functie aan te roepen:

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

BEWERKEN:Zoals opgemerkt in de opmerkingen, kun je dat zelfs terugbrengen tot één regel:

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

Of, als je niet eens de moeite wilt nemen om een sleep-functie te maken:

await require('util').promisify(setTimeout)(1000);

Antwoord 11, autoriteit 3%

Op Linux/nodejs werkt dit voor mij:

const spawnSync = required(‘child_process’).spawnSync;

var sleep = spawnSync(‘sleep’, [1.5]);

Het blokkeert, maar het is geen drukke wachtlus.

De tijd die je opgeeft is in seconden, maar kan ook een breuk zijn. Ik weet niet of andere besturingssystemen een soortgelijk commando hebben.


Antwoord 12, autoriteit 2%

Ik heb onlangs een eenvoudigere abstractie gemaakt met de naam wait.forom asynchrone functies aan te roepen in de synchronisatiemodus (gebaseerd op knooppuntvezels). Er is ook een versie die is gebaseerd op aankomende ES6-generatoren.

https://github.com/luciotato/waitfor

Met wait.forkun je elke standaard nodejs async-functie aanroepen, alsof het een sync-functie is, zonder de event-lus van de node te blokkeren.

Je kunt opeenvolgend coderen wanneer je het nodig hebt, wat (denk ik) perfect is om je scripts te vereenvoudigen voor persoonlijk gebruik.

met behulp van wait.forwordt uw 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. 

Ook elke asynchrone functie kan worden aangeroepen in de modus Sync.
Bekijk de voorbeelden.


Antwoord 13

Aangezien javascript-engine (v8) code uitvoert op basis van de volgorde van gebeurtenissen in de gebeurteniswachtrij, is er geen strikte eis dat javascript de uitvoering precies op een bepaald tijdstip activeert. Dat wil zeggen, wanneer u enkele seconden instelt om de code later uit te voeren, is het activeren van code puur gebaseerd op de volgorde in de gebeurteniswachtrij. Dus het activeren van de uitvoering van code kan meer tijd in beslag nemen dan de opgegeven tijd.

Dus Node.js volgt,

process.nextTick()

Om de code later uit te voeren in plaats daarvan in SetTimeout (). Bijvoorbeeld,

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

Antwoord 14

Met ES6-ondersteuning PromiseS, kunnen we ze gebruiken zonder hulp van derden.

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.

Gebruik het dan als volgt:

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

Merk op dat de doWhat-functie wordt de resolvecallback in de new Promise(...).

.

Merk ook op dat dit asynchrone slaap is. Het blokkeert de gebeurtenislus niet. Als u de slaap nodig hebt, gebruikt u deze bibliotheek die zich realiseert met blokkering met de hulp van C++ -bindingen. (Hoewel de behoefte aan een blokkerende slaap in knooppuntachtige async-omgevingen zeldzaam is.)

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


Antwoord 15

Probeer de belofte te gebruiken, het werkt voor mij in NODEJS

één voering

await new Promise(resolve => setTimeout(resolve, 5000));

of laat het als een functie in NodeJSom opnieuw te gebruiken

const sleep = async (milliseconds) => {
    await new Promise(resolve => setTimeout(resolve, milliseconds));
}

gebruik de functie zoals

await sleep(5000)

Antwoord 16

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');
});

Deze code hierboven is het neveneffect van het oplossen van het asynchrone callback hell-probleem van Javascript. Dit is ook de reden waarom ik denk dat Javascript een nuttige taal in de backend is. Eigenlijk is dit naar mijn mening de meest opwindende verbetering die in het moderne Javascript is geïntroduceerd. Om volledig te begrijpen hoe het werkt, moet de generator volledig worden begrepen. Het sleutelwoord functiongevolgd door een *wordt in modern Javascript een generatorfunctie genoemd. Het npm-pakket cobood een runner-functie om een generator te laten draaien.

In wezen een generatorfunctie bood een manier om de uitvoering van een functie met het trefwoord yieldte pauzeren, terwijl tegelijkertijd yieldin een generatorfunctie het mogelijk maakte om informatie uit te wisselen tussen de binnenkant van de generator en de beller. Dit leverde een mechanisme voor de beller om gegevens te extraheren uit een promisevan een asynchrone oproep en om de opgeloste gegevens terug te sturen naar de generator. In feite maakt het een asynchrone oproep synchroon.


Antwoord 17

Dit is een module met de smaak van moment.js, gebaseerd op de vuile blokkeringsaanpak die wordt voorgesteld door @atlex2. Gebruik dit alleen om te testen.

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

Antwoord 18

eenvoudig, we wachten 5 seconden totdat er een gebeurtenis plaatsvindt (dat wordt aangegeven door de variabele done die ergens anders in de code op true is ingesteld) of wanneer de time-out verloopt, controleren we deze elke 100 ms

   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;
        }
    })();

Antwoord 19

Voor sommige mensen werkt het geaccepteerde antwoord niet, ik heb dit andere antwoord gevonden en het werkt voor mij: Hoe kan ik een parameter doorgeven aan een setTimeout() callback?

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

‘hallo’ is de parameter die wordt doorgegeven, u kunt alle parameters doorgeven na de time-outtijd. Met dank aan @Fabio Phms voor het antwoord.


Antwoord 20

function doThen(conditional,then,timer) {
    var timer = timer || 1;
    var interval = setInterval(function(){
        if(conditional()) {
            clearInterval(interval);
            then();
        }
    }, timer);
}

Voorbeeld van gebruik:

var counter = 1;
doThen(
    function() {
        counter++;
        return counter == 1000;
    },
    function() {
        console.log("Counter hit 1000"); // 1000 repeats later
    }
)

Antwoord 21

Als je de uitvoering van je huidige thread alleen maar wilt onderbreken voor testdoeleinden, probeer dan dit:

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

Antwoord 22

De andere antwoorden zijn geweldig, maar ik dacht dat ik het anders zou aanpakken.

Als alles wat je echt zoekt is om een specifiek bestand in Linux te vertragen:

rm slowfile; mkfifo slowfile; perl -e 'select STDOUT; $| = 1; while(<>) {print $_; sleep(1) if (($ii++ % 5) == 0); }' myfile > slowfile  &

node myprog slowfile

Hierdoor slaapt u elke vijf regels 1 seconde. Het knooppuntprogramma zal net zo langzaam gaan als de schrijver. Als het andere dingen doet, gaan ze op normale snelheid verder.

De mkfifo creëert een first-in-first-out pijp. Het is wat dit werk maakt.
De perl-regel schrijft zo snel als je wilt. De $|=1 zegt dat de uitvoer niet moet worden gebufferd.


Antwoord 23

Ik heb, na het lezen van de antwoorden op deze vraag, een eenvoudige functie samengesteld die ook kan terugbellen, als je dat nodig hebt:

function waitFor(ms, cb) {
  var waitTill = new Date(new Date().getTime() + ms);
  while(waitTill > new Date()){};
  if (cb) {
    cb()
  } else {
   return true
  }
}

Antwoord 24

Voor meer informatie over

yield sleep(2000); 

je moet Redux-Sagacontroleren. Maar het is specifiek voor uw keuze voor Redux als uw modelraamwerk (hoewel strikt niet noodzakelijk).

Other episodes