Je développe une console comme un script pour des besoins personnels. Je dois pouvoir faire une pause prolongée, mais d'après mes recherches, node.js n'a aucun moyen de s'arrêter si nécessaire. Il est de plus en plus difficile de lire les informations des utilisateurs après un certain temps. J’ai vu du code, mais je pense qu’il doit contenir un autre code pour qu’il fonctionne, par exemple:
setTimeout(function() {
}, 3000);
Cependant, j'ai besoin de tout ce qui suit cette ligne de code pour s'exécuter après la période.
Par exemple,
//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.
J'ai aussi vu des choses comme
yield sleep(2000);
Mais node.js ne reconnaît pas cela.
Comment puis-je obtenir cette pause prolongée?
La meilleure façon de faire est de diviser votre code en plusieurs fonctions, comme ceci:
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);
C'est similaire à la solution de JohnnyHK , mais beaucoup plus nette et plus facile à étendre.
Une nouvelle réponse à une vieille question. Aujourd'hui (janvier 2017), c'est beaucoup plus facile. Vous pouvez utiliser la syntaxe new async/await
. Par exemple:
async function init(){
console.log(1)
await sleep(1000)
console.log(2)
}
function sleep(ms){
return new Promise(resolve=>{
setTimeout(resolve,ms)
})
}
Pour utiliser async/await
prêt à l'emploi, sans installation ni plug-in, vous devez utiliser node-v7 ou node-v8, à l'aide de l'indicateur --harmony
.
Plus d'informations:
Placez le code que vous voulez exécuter après le délai dans le rappel setTimeout
:
console.log('Welcome to My Console,');
setTimeout(function() {
console.log('Blah blah blah blah extra-blah');
}, 3000);
C'est une technique de blocage simple:
var waitTill = new Date(new Date().getTime() + seconds * 1000);
while(waitTill > new Date()){}
C'est bloquant dans la mesure où rien d'autre ne se passera dans votre script (comme des rappels). Mais puisqu'il s'agit d'un script de console, c'est peut-être ce dont vous avez besoin!
Vous pouvez utiliser ceci www.npmjs.com/package/sleep
var sleep = require('sleep');
sleep.sleep(10); // sleep for ten seconds
function sleep(millis) {
return new Promise(resolve => setTimeout(resolve, millis));
}
Pas de dépendances, pas de rappel enfer; c'est tout :-)
Considérant l'exemple donné dans la question, voici comment nous dormirions entre deux journaux de consoles:
async function main() {
console.log("Foo");
await sleep(2000);
console.log("Bar");
}
main();
L'inconvénient est que votre fonction principale doit maintenant être aussi async
. Mais, étant donné que vous écrivez déjà du code Javascript moderne, vous utilisez probablement (ou du moins devriez le faire!) async
/await
dans tout votre code, ce n'est donc vraiment pas un problème. Tous les navigateurs modernes actuels supportent it.
Donner un peu de perspicacité dans la fonction sleep
pour ceux qui ne sont pas habitués aux opérateurs async/await
et fat arrow, c’est la façon la plus verbeuse de l’écrire:
function sleep(millis) {
return new Promise(function (resolve, reject) {
setTimeout(function () { resolve(); }, millis);
});
}
L'utilisation de l'opérateur de flèche grasse, cependant, le rend encore plus petit (et plus élégant).
La solution la plus courte sans aucune dépendance:
await new Promise(done => setTimeout(done, 5000));
Cette question est assez ancienne, mais récemment, la V8 a ajouté des générateurs pouvant accomplir les tâches demandées par le PO. Les générateurs sont généralement les plus faciles à utiliser pour les interactions asynchrones avec l’aide d’une bibliothèque telle que suspend ou gen-run .
Voici un exemple utilisant susp:
suspend(function* () {
console.log('Welcome to My Console,');
yield setTimeout(suspend.resume(), 10000); // 10 seconds pass..
console.log('Blah blah blah blah extra-blah');
})();
Lecture connexe (par le biais d'une auto-promotion éhontée): Quel est le problème avec les générateurs? .
Le nœud prend en charge l'attente native:
const sleep = (waitTimeInMs) => new Promise(resolve => setTimeout(resolve, waitTimeInMs));
alors si vous pouvez utiliser des fonctions asynchrones:
await sleep(10000); // sleep for 10 seconds
ou:
sleep(10000).then(() => {
// This will execute 10 seconds from now
});
Je voulais un sommeil asynchrone fonctionnant sous Windows et Linux, sans monopoliser mon processeur avec une longue boucle while. J'ai essayé le paquet de sommeil mais il n'a pas été installé sur ma machine Windows. J'ai fini par utiliser:
https://www.npmjs.com/package/system-sleep
Pour l'installer, tapez:
npm install system-sleep
Dans votre code,
var sleep = require('system-sleep');
sleep(10*1000); // sleep for 10 seconds
Fonctionne comme un charme.
Sur Linux/nodejs cela fonctionne pour moi:
const spawnSync = require ('child_process'). spawnSync;
var sleep = spawnSync ('sommeil', [1.5]);
Il bloque, mais ce n'est pas une boucle d'attente occupée.
Le temps que vous spécifiez est en secondes mais peut être une fraction. Je ne sais pas si d'autres systèmes d'exploitation ont une commande similaire.
J'ai récemment créé une abstraction plus simple appelée wait.for pour appeler des fonctions asynchrones en mode sync (basé sur les fibres de nœud). Il existe également une version basée sur les générateurs ES6 à venir.
https://github.com/luciotato/waitfor
En utilisant wait.for, vous pouvez appeler n’importe quelle fonction async de noeud standard, comme s’il s’agissait d’une fonction de synchronisation, sans bloquer la boucle d’événement du noeud.
Vous pouvez coder de manière séquentielle quand vous en avez besoin, ce qui est (je suppose) parfait pour simplifier vos scripts pour un usage personnel.
en utilisant wait.for, votre code sera:
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.
De plus, toute fonction asynchrone peut être appelée en mode Sync ..... Vérifiez les exemples.
Si vous voulez "coder le golf", vous pouvez créer une version abrégée de certaines des autres réponses ici:
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
Mais à mon avis, la solution idéale consiste à utiliser la bibliothèque util
de Node et sa fonction promisify
, conçues pour ce type de choses (créer des versions basées sur des promesses de choses existantes non basées sur des promesses):
const util = require('util');
const sleep = util.promisify(setTimeout);
Dans les deux cas, vous pouvez faire une pause en utilisant simplement await
pour appeler votre fonction sleep
:
await sleep(1000); // sleep for 1s/1000ms
Depuis, le moteur javascript (v8) exécute le code en fonction de la séquence d'événements dans la file d'attente d'événements. Il n'est pas strict que javascript déclenche exactement l'exécution à une heure donnée. En d'autres termes, lorsque vous définissez quelques secondes pour exécuter le code ultérieurement, le code de déclenchement est purement basé sur la séquence dans la file d'attente des événements. Donc, le déclenchement de l'exécution du code peut prendre plus que le temps spécifié.
Alors Node.js suit,
process.nextTick()
pour exécuter le code ultérieurement à la place de setTimeout (). Par exemple,
process.nextTick(function(){
console.log("This will be printed later");
});
Avec ES6 prenant en charge Promise
s, nous pouvons les utiliser sans aucune aide de tiers.
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.
Ensuite, utilisez-le comme ceci:
const waitThenDo(howLong, doWhat) => {
return sleep(howLong).then(doWhat);
};
Notez que la fonction doWhat
devient le rappel resolve
au sein de la new Promise(...)
.
Notez également qu'il s'agit d'un sommeil ASYNCHRONE. Il ne bloque pas la boucle d'événement. Si vous avez besoin de bloquer le sommeil, utilisez cette bibliothèque qui réalise le blocage à l'aide de liaisons C++. (Bien que la nécessité d'un sommeil bloquant dans les environnements nodaux comme les environnements asynchrones soit rare.)
Ceci est un module aromatisé moment.js basé sur la approche de blocage sale proposée par @ atlex2 . Utilisez ceci uniquement pour tester.
const moment = require('moment');
let sleep = (secondsToSleep = 1) => {
let sleepUntill = moment().add(secondsToSleep, 'seconds');
while(moment().isBefore(sleepUntill)) { /* block the process */ }
}
module.exports = sleep;
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');
});
Ce code ci-dessus est l’effet secondaire du problème de l’enfer de rappel asynchrone par Javascript. C’est aussi la raison pour laquelle j'estime que cela fait de Javascript un langage utile dans le backend. En fait, c’est à mon avis l’amélioration la plus excitante introduite dans le Javascript moderne. Pour bien comprendre son fonctionnement, le fonctionnement du générateur doit être parfaitement compris. Le mot clé function
suivi d'un *
est appelé une fonction génératrice en Javascript moderne. Le package npm co
fournissait une fonction d'exécution pour exécuter un générateur.
Essentiellement, la fonction de générateur permettait de suspendre l'exécution d'une fonction avec le mot clé yield
et, dans le même temps, yield
dans une fonction de générateur, ce qui permettait l'échange d'informations entre le générateur et l'appelant. Cela fournissait un mécanisme permettant à l'appelant d'extraire les données d'une promise
d'un appel asynchrone et de renvoyer les données résolues au générateur. Effectivement, il rend un appel asynchrone synchrone.
simple, nous allons attendre 5 secondes qu'un événement se produise (ce qui serait indiqué par la variable done définie sur true quelque part dans le code) ou à l'expiration du délai imparti que nous vérifierons toutes les 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;
}
})();
Pour certaines personnes, la réponse acceptée ne fonctionne pas, j'ai trouvé cette autre réponse et elle fonctionne pour moi: Comment puis-je passer un paramètre à un rappel setTimeout ()?
var hello = "Hello World";
setTimeout(alert, 1000, hello);
'bonjour' est le paramètre passé, vous pouvez passer tous les paramètres après le délai d'attente. Merci à @Fabio Phms pour la réponse.
Consultez readline-sync ( https://www.npmjs.com/package/readline-sync )
Installer avec 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);
}
}
Peut-être pas la meilleure pratique mais fait le travail pour moi
Si vous avez juste besoin de suspendre à des fins de test, votre exécution de thread actuelle essayez ceci:
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