Як змінити інтервал часу в циклі для циклу відповідно до номера індексу / ітерації?


12

Оскільки я не міг коментувати, я змушений написати це повідомлення. Я отримав код нижче, який затримує / чекає рівно 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 секунду в першій ітерації. 2 секунди в секунді ітерації тощо. Остаточна затримка складе 5 секунд


2
Отже, ви хочете зробити 9 таймерів? Якщо так, то ваш код зробить те, що ви просите. Це не чекає рівно 3 секунди. Насправді таймери ніколи не будуть точними.
Скотт Маркус

1
Ваше запитання не має сенсу
DanStarns

2
Щойно випробував свій код у кодері: codepen.io/Connum/pen/BaaBMwW Ви отримуєте 9 повідомлень на 3000 мс один від одного - якщо це не те, що ви хочете (але з вашого питання це звучить так, як є), вкажіть, будь ласка, який ваш результат є.
Константин Грос

1
Ви, здається, не розумієте, як працює setTimeout в першу чергу - це не «затримка». Зараз ви отримуєте сповіщення через 3-секундні інтервали, тому що ви вже помножили 3000 i- якщо ви цього не зробили, то ви отримали б усі ці сповіщення одночасно .
04FS

3
Редагування питання, щоб зробити останнє речення жирним, насправді не допомагає вашій справі. Зараз вам сказали численні коментатори, що ваш код вже робить те, що ви просите (а точніше, не зовсім зрозуміло, про що ви дійсно просите, якщо це не ваш намічений результат).
Константин Грос

Відповіді:


6

Ось функція, яка з’явиться відразу, потім 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()


1
Мені дуже шкода, що я пропустив вашу відповідь, було так багато коментарів, нерозуміння, відповідей ... все одно я обираю вашу відповідь, як ви вперше вирішили те, що я попросив подякувати за ваш час, сер.
Майк

@Mike Lol Інші рішення корисні самі по собі, тому дякую за прийняття
mplungjan

Паван такий самий у синтаксисі ES6. Важко читати, але насправді те саме. Його редагування, щоб зробити так, було зроблено в той же час, коли я писав моє :)
mplungjan

8

Хоча це завдання можна вирішити обіцянками, реактивними потоками та іншими крутими інструментами (е, ніхто ще не запропонував використовувати працівників!), Це також можна вирішити з невеликою арифметикою.

Отже, ви хочете, щоб тайм-аути були в послідовності: 1s, попередній + 2s, попередній + 3s тощо. Ця послідовність становить: 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);
}


Математики ще живі !! :)
Білал Сіддікі

5

Ви можете спробувати використовувати функцію async / await (Обіцяння), щоб серіалізувати свій код:

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

Знадобився трохи часу, щоб розшифрувати ваше запитання 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();


Наприклад, якщо n = 5, то я хочу затримати цикл на 1 секунду в першій ітерації. 2 секунди в секунді ітерації і т. Д. Остаточна затримка складе 5 секунд.
Майк

так, це затримає 1 секунду для 1-ї ітерації, 2 секунди для 2-ї тощо, спробуйте
Pavan Skipo

Ваш опис не відповідає коду. Але це справляється з роботою
mplungjan

3

Цикл не чекає завершення функції очікування. Отже, коли цикл працює, він планує ваше сповіщення для кожного індексу.

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

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

3

Використовуйте рекурсивні дзвінки замість циклу

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


Наприклад, якщо n = 5, то я хочу затримати цикл на 1 секунду в першій ітерації. 2 секунди в секунді ітерації і т. Д. Остаточна затримка складе 5 секунд.
Майк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.