Use setTimeout en el bucle while en Node.js

Quiero mantener la ejecución de nodejs en setTimeout dentro de while loop. He usado la función asíncrono-cascada, pero no funcionó dentro del bucle while. así que he usado el siguiente código: –

var i = 3; while(i> 0) { setTimeout(function(){ console.log('start', i); setTimeout(function(){ console.log('timeout');}, 1000); console.log('end', i); i--; }, 1000); } console.log("execution ends"); 

Pero no obtuve la salida esperada. Mi salida esperada será como: –

  start3 timeout end3 start2 timeout end2 start1 timeout end1 execution ends 

forma 1: usar while loop

 var i = 3 var p = Promise.resolve(i) while (i > 0) { (i => { p = p.then(() => { return new Promise(function (resolve, reject) { console.log('start', i) setTimeout(function () { console.log('timeout') console.log('end', i) resolve() }, 1000) }) }) })(i) i-- } p = p.then(data => console.log('execution ends')) 

nodejs es asíncrono por naturaleza y setTimeout es más o menos como ejecutar algo en un nuevo hilo (más o menos porque JS es un solo hilo y usa un bucle de eventos).

Echa un vistazo a este paquete npm: https://www.npmjs.com/package/sleep

Eso debería hacer el truco…
Pero obviamente deberías usar el modo de sleep solo para propósitos de depuración. En el código de producción, es mejor incluir la naturaleza asíncrona de NodeJS y usar Promesas

Echa un vistazo a esto para obtener más detalles: bucle de eventos: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

setTimeout: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout

Promesa: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Hay algunos problemas con su progtwig con el resultado esperado. El primer i– funcionará solo después de 1000ms. En ese momento, demasiados bucles de tiempo habrían corrido. También setTimeOut no es bloqueante, por lo tanto, los execution ends la execution ends se consolidarán incluso antes de que se consolide el primer start . Para alcanzar el resultado esperado, puede realizar algunos cambios en el código:

 var i = 3;var j =3; while(j> 0) { setTimeout(function(){ console.log('start', i); console.log('timeout'); console.log('end', i); i--; }, 1000); j--; } if(j == 0){ setTimeout(function(){ console.log('execution ends'); }, 1000); } 

Por favor, intente a continuación un fragmento. Puede introducir llamadas de API O llamadas asíncronas en lugar de setTimeout en el método del temporizador.

 const timer = () => { return new Promise(res => { setTimeout(() => { console.log('timeout'); res(); }, 1000); }); } let i = 3; let temp; while (i > 0) { if (temp !== i) { temp = i; console.log('start', temp); timer().then(() => { console.log('end', temp); i -= 1; }); } } 

En primer lugar, debes entender que setTimeout() en Javascript no es bloqueante. Eso significa que todo lo que hace es progtwigr algo para que se ejecute más tarde y luego el rest de su código continúa ejecutándose de inmediato.

En su ejemplo de código en particular, tendrá un bucle infinito porque el bucle while continúa y continúa progtwigndo cada vez más temporizadores, pero hasta que el bucle while se detenga, ninguno de esos temporizadores puede funcionar. Y, hasta que uno de esos temporizadores pueda funcionar, su variable de bucle nunca cambia, por lo while bucle while nunca se detiene.

Para entender por qué funciona de esta manera, realmente tiene que entender el diseño basado en eventos de Javascript y node.js. Cuando llama a setTimeout() , progtwig un temporizador interno dentro del motor JS. Cuando ese temporizador se dispara, inserta un evento en la cola de eventos de Javascript. La próxima vez que el intérprete de JS termine con lo que estaba haciendo, verificará la cola de eventos y sacará el siguiente evento de la cola y lo ejecutará. Pero, el bucle while nunca deja de funcionar, por lo que nunca podrá acceder a ningún evento nuevo, por lo que nunca podrá ejecutar ninguno de sus eventos de temporizador.

Le mostraré tres formas diferentes de generar su salida deseada y todas se encuentran en fragmentos de código ejecutables para que pueda ejecutarlos directamente en la respuesta para ver sus resultados.

La primera técnica se lleva a cabo en Javascript simple con solo configurar los temporizadores en diferentes momentos del futuro, de manera que las distintas salidas deseadas se activen en la secuencia correcta:

Temporizadores que varían

 let cntr = 3; for (let i = 1; i <= 3; i++) { // schedule timers at different increasing delays setTimeout(function() { console.log('start', cntr); setTimeout(function() { console.log('timeout'); console.log('end', cntr); --cntr; if (cntr === 0) { console.log("execution ends"); } }, 1000); }, i * 2000); } 

no obtuvo la salida esperada porque hay un cierre en su código, mejore su código de esta manera:

 var i = 3; while(i> 0) { setTimeout(( function(i){ return function(){ console.log('start', i); setTimeout(function(){ console.log('timeout');}, 1000); console.log('end', i); i--; } } )(i), 1000); }