Как динамически изменить интервал времени в цикле For в соответствии с индексом / номером итерации? - PullRequest
12 голосов
/ 04 октября 2019

Поскольку я не мог комментировать, я вынужден написать этот пост. Я получил следующий код, который задерживает / ждет ровно 1 секунду или 1000 миллисекунд -

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

Но как я могу задержать это i * 1000 секунд вместо фиксированных 1000 миллисекунд, чтобы ожидание зависело от номера итерации?

Например,если n = 5, то я хочу, чтобы задержка цикла составляла 1 секунду в 1-й итерации. 2 секунды во второй итерации и т. Д., Окончательная задержка составит 5 секунд.

Ответы [ 7 ]

8 голосов
/ 04 октября 2019

Хотя эту задачу можно решить с помощью обещаний, реактивных потоков и других интересных инструментов (эй, никто еще не предлагал использовать рабочих!), Ее также можно решить с помощью небольшой арифметики.

Так что вам нужны тайм-аутыв последовательности: 1 с, предыдущий + 2 с, предыдущий + 3 с и т. д. Эта последовательность: 1, 3, 6, 10, 15 ... и ее формула a[n] = n * (n + 1) / 2. Зная, что ...

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);
}
6 голосов
/ 04 октября 2019

Вот функция, которая будет отображаться немедленно, затем через 1 секунду, через 2 секунды после, через 3 секунды после этого и т. Д. Никакой специальной математики, никаких обещаний не требуется

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()
5 голосов
/ 04 октября 2019

Вы можете попробовать использовать async / await (Promises) для сериализации вашего кода:

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 голосов
/ 04 октября 2019

Мне понадобилось время, чтобы расшифровать твой вопрос xD, но ты этого хочешь?

Это будет запускать console.log с задержкой i * 1000 каждый раз. поэтому в первый раз это будет 1 секунда (1 * 1000), затем это будет 2 секунды и т. д.

let i = 0;
loop = () => {
  setTimeout(() => {
    console.log(new Date()); // for clarity
    i++;
    if (i < 10) {
      loop();
    }
  }, i * 1000)
};
loop();
3 голосов
/ 04 октября 2019

Цикл не ожидает завершения функции тайм-аута. Поэтому, когда цикл запускается, он планирует ваше оповещение для каждого индекса.

Вы можете использовать функцию, которая будет работать в соответствии с вашим индексом, но запланирована в то же время. Вы можете почувствовать разницу в 3 секунды.

function test(i){
    setTimeout( function timer(){
        console.log("hello world" + i);
    }, i*3000);
}
for (let i=1; i<4; i++) {
   test(i);
}
3 голосов
/ 04 октября 2019

Использовать рекурсивные вызовы вместо цикла

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);
0 голосов
/ 04 октября 2019

ON EXPLORING @mbojko 's ответ

for (let i = 1; i <= 5; i++) {
  setTimeout(function timer() {
    console.log("Delaying - " + i + " seconds");
  }, 1000 * i * (i + 1) / 2);
}

function Explanation(){
  //This comes from the finite arithmetic series n(n+1)/2
            //http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/runsums/triNbProof.html
            //for first five iterations..
            //1000 * 1 * (1+1)/2 = 1
            //1000 * 2 * (2+1)/2 = 3
            //1000 * 3 * (3+1)/2 = 6
            //1000 * 4 * (4+1)/2 = 10
            //1000 * 5 * (5+1)/2 = 15
}
...