node - yield javascript
Cómo puedo esperar en Node.js(Javascript), necesito hacer una pausa por un período de tiempo (23)
Estoy desarrollando una consola como script para necesidades personales ... Necesito poder hacer una pausa por un período prolongado de tiempo, pero como node.js de mi investigación no tiene forma de detenerse como se requiere ... Se está poniendo difícil para leer la información de los usuarios después de un período de tiempo ... vi un código por ahí, pero creo que tienen que tener otros códigos para que funcionen, como:
setTimeout(function() {
}, 3000);
Pero este problema es que necesito todo después de esta línea de código para ejecutarse después del período de tiempo ...
Por ejemplo,
//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.
También he visto cosas como
yield sleep(2000);
Pero node.js no reconoce esto ....
Si alguien está dispuesto a ayudar, es muy apreciado.
Función de sueño simple y elegante con Javascript moderno
function sleep(millis) {
return new Promise(resolve => setTimeout(resolve, millis));
}
Sin dependencias, sin infierno de devolución de llamadas; Eso es :-)
Teniendo en cuenta el ejemplo dado en la pregunta, así es como dormiríamos entre dos registros de consola:
async function main() {
console.log("Foo");
await sleep(2000);
console.log("Bar");
}
main();
El "inconveniente" es que su función principal ahora también tiene que ser async
. Pero, considerando que ya está escribiendo código Javascript moderno, es probable que esté (o al menos debería estarlo) usando async
/ await
todo su código, por lo que realmente no es un problema. Todos los navegadores modernos de hoy lo support .
Dando un poco de información sobre la función de sleep
para aquellos que no están acostumbrados a los operadores async/await
y flecha gruesa, esta es la forma detallada de escribirlo:
function sleep(millis) {
return new Promise(function (resolve, reject) {
setTimeout(function () { resolve(); }, millis);
});
}
Sin embargo, el uso del operador de flecha gruesa lo hace aún más pequeño (y más elegante).
Coloque el código que desea ejecutar después de la demora dentro de la setTimeout
llamada setTimeout
:
console.log(''Welcome to My Console,'');
setTimeout(function() {
console.log(''Blah blah blah blah extra-blah'');
}, 3000);
Dado que, el motor javascript (v8) ejecuta el código basado en la secuencia de eventos en la cola de eventos, no hay ningún criterio estricto de que javascript desencadene la ejecución exactamente después del tiempo especificado. Es decir, cuando configura algunos segundos para ejecutar el código más tarde, el código de activación se basa únicamente en la secuencia en la cola de eventos. Por lo tanto, la ejecución de código puede demorar más de lo especificado.
Entonces Node.js sigue,
process.nextTick()
para ejecutar el código más tarde en lugar de setTimeout (). Por ejemplo,
process.nextTick(function(){
console.log("This will be printed later");
});
Eche un vistazo a readline-sync ( https://www.npmjs.com/package/readline-sync )
Instalar con 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);
}
}
Tal vez no sea la mejor práctica pero hace el trabajo por mí
En Linux / nodejs esto funciona para mí:
const spawnSync = require (''child_process''). spawnSync;
var sleep = spawnSync (''sleep'', [1.5]);
Está bloqueando, pero no es un bucle de espera ocupado.
El tiempo que especifique es en segundos, pero puede ser una fracción. No sé si otros sistemas operativos tienen un comando similar.
Esta es una técnica de bloqueo simple:
var waitTill = new Date(new Date().getTime() + seconds * 1000);
while(waitTill > new Date()){}
Se está bloqueando en la medida en que no sucederá nada más en su script (como devoluciones de llamada). Pero como se trata de un script de consola, ¡tal vez sea lo que necesitas!
Esta pregunta es bastante antigua, pero recientemente V8 ha agregado Generadores que pueden lograr lo que el OP solicitó. En general, los generadores son más fáciles de usar para las interacciones asíncronas con la asistencia de una biblioteca, como suspend o gen-run .
Aquí hay un ejemplo usando suspender:
suspend(function* () {
console.log(''Welcome to My Console,'');
yield setTimeout(suspend.resume(), 10000); // 10 seconds pass..
console.log(''Blah blah blah blah extra-blah'');
})();
Lectura relacionada (a través de una auto promoción descarada): ¿Cuál es el problema con los generadores? .
Este es un módulo de moment.js con sabor basado en el enfoque de bloqueo sucio sugerido por @ atlex2 . Use esto solo para pruebas .
const moment = require(''moment'');
let sleep = (secondsToSleep = 1) => {
let sleepUntill = moment().add(secondsToSleep, ''seconds'');
while(moment().isBefore(sleepUntill)) { /* block the process */ }
}
module.exports = sleep;
La mejor manera de hacer esto es dividir tu código en múltiples funciones, como esta:
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 similar a la solución de JohnnyHK , pero mucho más limpia y fácil de extender.
La solución más corta sin ninguna dependencia:
await new Promise(done => setTimeout(done, 5000));
Las otras respuestas son geniales, pero pensé que tomaría un tacto diferente.
Si lo que realmente está buscando es ralentizar un archivo específico en linux:
rm slowfile; mkfifo slowfile; perl -e ''select STDOUT; $| = 1; while(<>) {print $_; sleep(1) if (($ii++ % 5) == 0); }'' myfile > slowfile &
nodo myprog slowfile
Esto dormirá 1 segundo cada cinco líneas. El programa del nodo irá tan lento como el escritor. Si está haciendo otras cosas, continuarán a velocidad normal.
El mkfifo crea una tubería primero en entrar, primero en salir. Es lo que hace que esto funcione. La línea de Perl escribirá tan rápido como quieras. El $ | = 1 dice que no se almacena en buffer la salida.
Para algunas personas, la respuesta aceptada no funciona, encontré esta otra respuesta y está funcionando para mí: ¿Cómo puedo pasar un parámetro a una devolución de llamada setTimeout ()?
var hello = "Hello World";
setTimeout(alert, 1000, hello);
''hola'' es el parámetro que se pasa, puede pasar todos los parámetros después del tiempo de espera. Gracias a @Fabio Phms por la respuesta.
Para más información sobre
yield sleep(2000);
Usted debe comprobar Redux-Saga . Pero es específico para su elección de Redux como marco de su modelo (aunque estrictamente no es necesario).
Puede utilizar este www.npmjs.com/package/sleep
var sleep = require(''sleep'');
sleep.sleep(10); // sleep for ten seconds
Quería un sueño asíncrono que funcionara en Windows y Linux, sin saturar mi CPU con un bucle largo. Probé el paquete de suspensión pero no se instalaría en mi caja de Windows. Terminé usando:
https://www.npmjs.com/package/system-sleep
Para instalarlo, escriba:
npm install system-sleep
En tu código,
var sleep = require(''system-sleep'');
sleep(10*1000); // sleep for 10 seconds
Funciona de maravilla.
Recientemente he creado una abstracción más simple llamada wait.for para llamar funciones asíncronas en modo de sincronización (basado en fibras de nodo). También hay una versión basada en los próximos generadores ES6.
https://github.com/luciotato/waitfor
Usando wait.for , puede llamar a cualquier función asíncrona de nodejs estándar, como si fuera una función de sincronización, sin bloquear el bucle de eventos del nodo.
Puede codificar secuencialmente cuando lo necesite, lo cual es (supongo) perfecto para simplificar sus scripts para uso personal.
usando wait.for tu código será:
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.
También se puede llamar a cualquier función asíncrona en modo Sync . Revisa los ejemplos.
Reuní, después de haber leído las respuestas en esta pregunta, una función simple que también puede hacer una devolución de llamada, si necesita eso:
function waitFor(ms, cb) {
var waitTill = new Date(new Date().getTime() + ms);
while(waitTill > new Date()){};
if (cb) {
cb()
} else {
return true
}
}
Si ES6 es compatible con Promise
s, podemos usarlos sin ayuda de terceros.
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.
Entonces úsalo así:
const waitThenDo(howLong, doWhat) => {
return sleep(howLong).then(doWhat);
};
Tenga en cuenta que la función doWhat
convierte en la devolución de llamada de resolve
dentro de la new Promise(...)
.
También tenga en cuenta que esto es el sueño ASINCRÓNICO. No bloquea el bucle de eventos. Si necesita bloquear el sueño, use esta biblioteca que realiza el bloqueo del sueño con la ayuda de los enlaces de C ++. (Aunque la necesidad de un bloqueo del sueño en entornos asíncronos como Node es rara).
Si desea "codificar golf", puede hacer una versión más corta de algunas de las otras respuestas aquí:
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
Pero, en realidad, la respuesta ideal en mi opinión es utilizar la biblioteca util
de Node y su función promisify
, que está diseñada para este tipo de cosas exactamente (hacer versiones basadas en promesas de cosas previamente no basadas en promesas):
const util = require(''util'');
const sleep = util.promisify(setTimeout);
En cualquier caso, puede hacer una pausa simplemente utilizando await
para llamar a su función de sleep
:
await sleep(1000); // sleep for 1s/1000ms
Si solo necesita suspender con el fin de probar su ejecución de subprocesos actual, intente esto:
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
Una nueva respuesta a una vieja pregunta. Hoy (enero de 2017) es mucho más fácil. Puede utilizar la nueva sintaxis async/await
. Por ejemplo:
async function init(){
console.log(1)
await sleep(1000)
console.log(2)
}
function sleep(ms){
return new Promise(resolve=>{
setTimeout(resolve,ms)
})
}
Para usar async/await
out of the box sin instalar y los complementos, debe usar node-v7 o node-v8, usando el indicador --harmony
.
Más información:
- Bandera de armonía en Nodejs: https://nodejs.org/en/docs/es6/
- Todas las versiones de NodeJS para descargar: https://nodejs.org/en/download/releases/
simple, vamos a esperar 5 segundos para que ocurra algún evento (lo que se indicaría mediante la variable done establecida en true en otra parte del código) o cuando expire el tiempo de espera, lo verificaremos cada 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;
}
})();
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'');
});
Este código anterior es el efecto secundario de resolver el problema del infierno de devolución de llamada asíncrona de Javascript. Esta es también la razón por la que creo que hace de Javascript un lenguaje útil en el backend. En realidad, esta es la mejora más emocionante introducida al Javascript moderno en mi opinión. Para comprender completamente cómo funciona, cómo debe funcionar el generador debe entenderse completamente. La palabra clave de function
seguida de un *
se denomina función de generador en Javascript moderno. El paquete npm co
proporcionó una función de corredor para ejecutar un generador.
Esencialmente, la función del generador proporcionó una forma de pausar la ejecución de una función con la palabra clave de yield
, al mismo tiempo, el yield
en una función del generador hizo posible el intercambio de información entre el generador y la persona que llama. Esto proporcionó un mecanismo para que la persona que llama extraiga datos de una promise
de una llamada asíncrona y devuelva los datos resueltos al generador. Efectivamente, hace una llamada asíncrona sincrónica.