Come modificare dinamicamente il tempo di intervallo in For Loop in base al numero indice / iterazione?


12

Dal momento che non ho potuto commentare, sono costretto a scrivere questo post. Ho ottenuto il codice seguente che ritarda / attende esattamente 1 secondo o 1000 millisecondi -

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

Ma come posso ritardare i * 1000 secondi anziché i fissi 1000 millisecondi, quindi l'attesa dipende dal numero di iterazione?

Ad esempio, se n = 5, quindi voglio il ritardo del loop di 1 secondo nella prima iterazione. 2 secondi nella seconda iterazione e così via .. il ritardo finale sarà di 5 secondi.


2
Quindi vuoi fare 9 timer? In tal caso, il tuo codice farà quello che stai chiedendo. Non attende esattamente 3 secondi. In effetti, i timer non saranno mai esatti.
Scott Marcus,

1
la tua domanda non ha senso
DanStarns

2
Ho appena provato il tuo codice in un codice: codepen.io/Connum/pen/BaaBMwW Ricevi 9 messaggi a 3000 ms di distanza - se non è quello che vuoi (ma dalla tua domanda sembra che sia), per favore specifica qual è il tuo risultato previsto è.
Constantin Groß,

1
Lei non sembra di capire come funziona setTimeout, in primo luogo - è non è un “ritardo”. In questo momento, ricevi gli avvisi a intervalli di 3 secondi, perché hai già moltiplicato i 3000 con i- se non lo facessi, riceveresti tutti quegli avvisi contemporaneamente .
04FS,

3
Modificare la domanda per rendere audace l'ultima frase non aiuta davvero il tuo caso. Più commentatori ti hanno ora detto che il tuo codice fa già quello che stai chiedendo (o meglio, non è del tutto chiaro cosa stai REALMENTE chiedendo, se non è il risultato desiderato).
Constantin Groß,

Risposte:


6

Ecco una funzione che verrà mostrata immediatamente, quindi 1 secondo dopo, 2 secondi dopo, 3 secondi dopo ecc. Nessuna matematica speciale, nessuna promessa necessaria

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
Sono estremamente dispiaciuto di aver perso la tua risposta, ci sono stati così tanti commenti, incomprensioni, risposte ... comunque sto scegliendo la tua risposta poiché tu eri il primo a aver risolto ciò che ti avevo chiesto grazie per il tuo tempo, signore.
Mike,

@Mike Lol. Le altre soluzioni sono utili di per sé, quindi grazie per accettare
mplungjan il

Pavan è lo stesso nella sintassi ES6. Più difficile da leggere ma in realtà è lo stesso. La sua modifica per farlo è stata fatta contemporaneamente a quella che ho scritto il mio :)
mplungjan,

8

Sebbene questo compito possa essere risolto con promesse, flussi reattivi e altri strumenti interessanti (ehi, nessuno ha ancora suggerito di usare i lavoratori!), Può anche essere risolto con un po 'di aritmetica.

Quindi vuoi timeout in una sequenza: 1s, il precedente + 2s, il precedente + 3s e così via. Questa sequenza è: 1, 3, 6, 10, 15 ... e la sua formula è a[n] = n * (n + 1) / 2. Sapendo ciò...

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


I matematici sono ancora vivi !! :)
Bilal Siddiqui,

5

Puoi provare a usare async / await (Promises), per serializzare il tuo codice:

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

Mi ci è voluto del tempo per decifrare la tua domanda xD, ma è questo quello che vuoi?

Questo continuerà a sparare console.log con i * 1000 di ritardo ogni volta. quindi la prima volta sarà lunga 1 secondo (1 * 1000), poi saranno 2 secondi e così via.

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


Ad esempio, se n = 5, quindi voglio il ritardo del loop di 1 secondo nella prima iterazione. 2 secondi nella seconda iterazione e così via .. il ritardo finale sarà di 5 secondi.
Mike,

Sì, questo ritarderà 1 secondo per la prima iterazione, 2 secondi per la seconda e così via, provalo
Pavan Skipo

La tua descrizione non corrisponde al codice. Ma fa il suo lavoro
mplungjan il

3

Il loop non attende il completamento della funzione di timeout. Pertanto, quando il ciclo viene eseguito, pianifica l'avviso per ciascun indice.

È possibile utilizzare una funzione che verrà eseguita in base all'indice ma pianificata allo stesso tempo. Puoi sentire la differenza di 3 secondi.

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

3

Usa chiamate ricorsive invece che per 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);


Ad esempio, se n = 5, quindi voglio il ritardo del loop di 1 secondo nella prima iterazione. 2 secondi nella seconda iterazione e così via .. il ritardo finale sarà di 5 secondi.
Mike,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.