¿Cómo cambiar el tiempo de intervalo dinámicamente en el bucle For según el índice / número de iteración?


12

Como no pude comentar, me veo obligado a escribir esta publicación. Obtuve el siguiente código que retrasa / espera exactamente 1 segundo o 1000 milisegundos:

let n = 5;
for (let i=1; i<n; i++)
{
  setTimeout( function timer()
  {
      console.log("hello world");
  }, i*1000 );
}

Pero, ¿cómo puedo retrasarlo i * 1000 segundos en lugar de 1000 milisegundos fijos para que la espera dependa del número de iteración?

Por ejemplo, si n = 5, entonces quiero que el bucle demore 1 segundo en la primera iteración. 2 segundos en la segunda iteración, y así sucesivamente ... el retraso final será de 5 segundos.


2
¿Entonces quieres hacer 9 temporizadores? Si es así, entonces su código hará lo que está pidiendo. No espera exactamente 3 segundos. De hecho, los temporizadores nunca serán exactos.
Scott Marcus el

1
su pregunta no tiene sentido
DanStarns

2
Acabo de probar su código en un codepen: codepen.io/Connum/pen/BaaBMwW Obtiene 9 mensajes con una separación de 3000 ms, si eso no es lo que desea (pero de su pregunta suena como es), especifique cuál es el resultado deseado es.
Constantin Groß

1
No pareces entender cómo funciona setTimeout en el primer lugar - es no un “retraso”. En este momento, está recibiendo sus alertas en intervalos de 3 segundos, porque ya multiplicó el 3000 con i: si no lo hizo, entonces recibirá todas esas alertas al mismo tiempo.
04FS

3
Editar la pregunta para poner en negrita tu última oración no ayuda mucho a tu caso. Varios comentaristas le han dicho que su código ya hace lo que está pidiendo (o más bien, no está del todo claro qué está pidiendo REALMENTE, si ese no es el resultado previsto).
Constantin Groß

Respuestas:


6

Aquí hay una función que se mostrará de inmediato, luego 1 segundo más tarde, 2 segundos después, 3 segundos después de eso, etc. No se necesitan cálculos especiales, no se necesitan promesas.

const n = 5;
let cnt=0;

function show() {
  console.log("call "+cnt,"delay: ",cnt,"sec");
  cnt++;
  if (cnt > n) return; // we are done
  setTimeout(show, cnt*1000 ); // cnt seconds later
}
show()


1
Lamento mucho haber perdido su respuesta, hubo tantos comentarios, malentendidos, respuestas ... de todos modos, elijo su respuesta, ya que usted fue el primero en resolver lo que le pedí, gracias por su tiempo, señor.
Mike

@ Mike Lol. Las otras soluciones son útiles por derecho propio, así que gracias por aceptar
mplungjan

Pavan es igual en la sintaxis de ES6. Es más difícil de leer pero de hecho es lo mismo. Su edición para hacerlo así se hizo al mismo tiempo que escribí el mío :)
mplungjan

8

Si bien esta tarea podría resolverse con promesas, flujos reactivos y otras herramientas geniales (¡hey, nadie ha sugerido usar trabajadores todavía!), También puede resolverse con un poco de aritmética.

Entonces desea tiempos de espera en una secuencia: 1s, el anterior + 2s, el anterior + 3s, y así sucesivamente. Esta secuencia es: 1, 3, 6, 10, 15 ... y su fórmula es a[n] = n * (n + 1) / 2. Sabiendo que...

let n = 6;
console.log(new Date().getSeconds());

for (let i = 1; i < n; i++) {
  setTimeout(function timer() {
    console.log(new Date().getSeconds());
  }, 1000 * i * (i + 1) / 2);
}


¡Los matemáticos todavía están vivos! :)
Bilal Siddiqui

5

Puede intentar usar async / await (Promesas) para serializar su código:

const waitSeconds = seconds => new Promise(resolve => setTimeout(resolve, seconds))

async function main () {
 let oldDate = new Date()
 let newDate
 
 /* 
  * If you put 'await' inside the loop you can synchronize the async code, and simulate
  * a sleep function
  */
 for (let i=1; i<5; i++) {
    await waitSeconds(i*1000)
    newDate = new Date()   
    console.log(`Loop for i=${i}, elapsed=${moment(newDate).diff(oldDate, 'seconds')} seconds`)
    oldDate = newDate
 }
 
 console.log('End')
}

main()
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>


5

Me tomó un tiempo descifrar tu pregunta xD, pero ¿es esto lo que quieres?

Esto seguirá disparando console.log con i * 1000 de retraso cada vez. así que la primera vez durará 1 segundo (1 * 1000), luego será de 2 segundos y así sucesivamente.

let i = 0;
loop = () => {
  setTimeout(() => {
    console.log(new Date()); // for clarity
    i++;
    if (i < 10) {
      loop();
    }
  }, i * 1000)
};
loop();


Por ejemplo, si n = 5, entonces quiero que el bucle demore 1 segundo en la primera iteración. 2 segundos en la segunda iteración, y así sucesivamente ... el retraso final será de 5 segundos.
Mike

sí, esto retrasará 1 segundo para la primera iteración, 2 segundos para la segunda y así sucesivamente, pruébalo
Pavan Skipo

Su descripción no coincide con el código. Pero hace el trabajo
mplungjan

3

El bucle no espera a que se complete la función de tiempo de espera. Entonces, cuando el ciclo se ejecuta, programa su alerta para cada índice.

Puede usar una función que se ejecutará de acuerdo con su índice pero programada al mismo tiempo. Puedes sentir la diferencia de 3 segundos.

function test(i){
    setTimeout( function timer(){
        console.log("hello world" + i);
    }, i*3000);
}
for (let i=1; i<4; i++) {
   test(i);
}

3

Use llamadas recursivas en lugar de for loop

let i=1;
function a(i) {
  if (i > 5)
    return
  else
    b("message", i)
}

function b(s, f) {
  setTimeout(function timer() {
    console.log(s + " " + f + " seconds");
  }, f * 1000);
  a(++i);
}
a(i);


Por ejemplo, si n = 5, entonces quiero que el bucle demore 1 segundo en la primera iteración. 2 segundos en la segunda iteración, y así sucesivamente ... el retraso final será de 5 segundos.
Mike
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.