Wie ändere ich die Intervallzeit dynamisch in der For-Schleife entsprechend der Index- / Iterationsnummer?

12

Da ich keinen Kommentar abgeben konnte, bin ich gezwungen, diesen Beitrag zu schreiben. Ich habe den folgenden Code erhalten, der genau 1 Sekunde oder 1000 Millisekunden verzögert / wartet -

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

Aber wie kann ich es auf 1000 Sekunden anstatt auf 1000 Millisekunden verzögern, damit das Warten von der Iterationsnummer abhängt?

Wenn zum Beispiel n = 5 ist, möchte ich die Schleifenverzögerung 1 Sekunde in der 1. Iteration. 2 Sekunden in der zweiten Iteration und so weiter. Die endgültige Verzögerung beträgt 5 Sekunden.

Mike
quelle
2
Du willst also 9 Timer machen? Wenn ja, dann wird Ihr Code tun, was Sie fragen. Es wartet nicht genau 3 Sekunden. In der Tat werden Timer niemals genau sein.
Scott Marcus
1
Ihre Frage macht keinen Sinn
DanStarns
2
Probieren Sie Ihren Code einfach in einem Codepen aus: codepen.io/Connum/pen/BaaBMwW Sie erhalten 9 Nachrichten im Abstand von 3000 ms - wenn Sie dies nicht möchten (aber aus Ihrer Frage heraus klingt es so), geben Sie bitte Ihr beabsichtigtes Ergebnis an ist.
Constantin Groß
1
Sie scheinen nicht zu verstehen, wie setTimeout überhaupt funktioniert - es ist keine „Verzögerung“. Im Moment erhalten Sie Ihre Warnungen in Intervallen von 3 Sekunden, da Sie die 3000 bereits mit multipliziert haben. iWenn Sie dies nicht tun, erhalten Sie alle diese Warnungen gleichzeitig .
04FS
3
Das Bearbeiten der Frage, um Ihren letzten Satz fett zu machen, hilft Ihrem Fall nicht wirklich. Mehrere Kommentatoren haben Ihnen jetzt mitgeteilt, dass Ihr Code bereits das tut, wonach Sie fragen (oder besser gesagt, es ist nicht ganz klar, wonach Sie tatsächlich fragen, wenn dies nicht Ihr beabsichtigtes Ergebnis ist).
Constantin Groß

Antworten:

6

Hier ist eine Funktion, die sofort angezeigt wird, dann 1 Sekunde später, 2 Sekunden danach, 3 Sekunden danach usw. Keine spezielle Mathematik, keine Versprechen erforderlich

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()

mplungjan
quelle
1
Es tut mir sehr leid, dass ich Ihre Antwort verpasst habe, es gab so viele Kommentare, Missverständnisse, Antworten ... trotzdem wähle ich Ihre Antwort, als Sie der erste waren, der gelöst hat, was ich gefragt habe, danke für Ihre Zeit, Sir.
Mike
@ Mike Lol. Die anderen Lösungen sind für sich genommen nützlich, also danke für die Annahme
mplungjan
Pavans ist in der ES6-Syntax dasselbe. Schwer zu lesen, aber es ist in der Tat das gleiche. Seine Bearbeitung, um es so zu machen, wurde zur gleichen Zeit gemacht, als ich meine schrieb :)
mplungjan
8

Während diese Aufgabe mit Versprechungen, reaktiven Streams und anderen coolen Tools gelöst werden könnte (hey, noch hat niemand vorgeschlagen, Arbeiter einzusetzen!), Kann sie auch mit ein wenig Arithmetik gelöst werden.

Sie möchten also Zeitüberschreitungen in einer Sequenz: 1s, die vorherige + 2s, die vorherige + 3s und so weiter. Diese Sequenz lautet: 1, 3, 6, 10, 15 ... und ihre Formel lautet a[n] = n * (n + 1) / 2. Wissend, dass...

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

mbojko
quelle
Mathematiker leben noch !! :)
Bilal Siddiqui
5

Sie können versuchen, mit async / await (Promises) Ihren Code zu serialisieren:

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>

Mauro Stepanoski
quelle
5

Ich habe einige Zeit gebraucht, um Ihre Frage xD zu entschlüsseln, aber ist es das, was Sie wollen?

Dadurch wird console.log jedes Mal mit einer Verzögerung von i * 1000 ausgelöst . Das erste Mal ist es 1 Sekunde lang (1 * 1000), das nächste Mal 2 Sekunden und so weiter.

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

Pavan Skipo
quelle
Wenn zum Beispiel n = 5 ist, möchte ich die Schleifenverzögerung 1 Sekunde in der 1. Iteration. 2 Sekunden in der zweiten Iteration und so weiter. Die endgültige Verzögerung beträgt 5 Sekunden.
Mike
yup dies wird 1 Sekunde für die 1. Iteration, 2 Sekunden für die 2. und so weiter verzögern, versuchen Sie es
Pavan Skipo
Ihre Beschreibung stimmt nicht mit dem Code überein. Aber es macht den Job
mplungjan
3

Die Schleife wartet nicht auf den Abschluss der Timeout-Funktion. Wenn die Schleife ausgeführt wird, wird Ihre Warnung für jeden Index geplant.

Sie können eine Funktion verwenden, die gemäß Ihrem Index ausgeführt wird, aber gleichzeitig geplant ist. Sie können den Unterschied von 3 Sekunden fühlen.

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

Verwenden Sie rekursive Aufrufe anstelle der for-Schleife

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

Ellipse
quelle
Wenn zum Beispiel n = 5 ist, möchte ich die Schleifenverzögerung 1 Sekunde in der 1. Iteration. 2 Sekunden in der zweiten Iteration und so weiter. Die endgültige Verzögerung beträgt 5 Sekunden.
Mike