Bagaimana Mengubah Waktu Interval Secara Dinamis dalam Untuk Loop Menurut Indeks / Nomor iterasi?

12

Karena saya tidak bisa berkomentar, saya terpaksa menulis posting ini. Saya mendapatkan kode di bawah ini yang menunda / menunggu tepat 1 detik atau 1000 milidetik -

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

Tapi bagaimana saya bisa menunda i * 1000 detik, bukannya tetap 1000 milidetik sehingga menunggu tergantung pada nomor iterasi?

Misalnya, jika n = 5, maka saya ingin loop tunda 1 detik di iterasi 1. 2 detik dalam iterasi kedua, dan seterusnya .. penundaan akhir akan 5 detik.

Mike
sumber
2
Jadi, Anda ingin membuat 9 timer? Jika demikian, maka kode Anda akan melakukan apa yang Anda minta. Itu tidak menunggu tepat 3 detik. Bahkan, timer tidak akan pernah tepat.
Scott Marcus
1
pertanyaan Anda tidak masuk akal
DanStarns
2
Baru saja mencoba kode Anda dalam codepen: codepen.io/Connum/pen/BaaBMwW Anda mendapatkan 9 pesan terpisah sejauh 3000 ms - jika itu bukan yang Anda inginkan (tetapi dari pertanyaan Anda, itu terdengar seperti itu), harap tentukan hasil yang Anda inginkan adalah.
Constantin Groß
1
Anda sepertinya tidak mengerti bagaimana setTimeout bekerja sejak awal - ini bukan "penundaan". Saat ini, Anda mendapatkan lansiran dalam interval 3 detik, karena Anda sudah mengalikan 3000 dengan i- jika Anda tidak melakukan itu, maka Anda akan mendapatkan semua lansiran itu pada waktu yang sama .
04FS
3
Mengedit pertanyaan agar kalimat terakhir Anda menjadi tebal tidak benar-benar membantu kasus Anda. Anda sekarang telah diberitahu oleh banyak komentator bahwa kode Anda sudah melakukan apa yang Anda minta (atau lebih tepatnya, tidak jelas apa yang sebenarnya Anda minta, jika itu bukan hasil yang Anda inginkan).
Constantin Groß

Jawaban:

6

Berikut adalah fungsi yang akan segera ditampilkan, lalu 1 detik kemudian, 2 detik setelah dari, 3 detik setelah itu dll. Tidak ada matematika khusus, tidak ada janji yang dibutuhkan

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
sumber
1
Saya sangat menyesal saya melewatkan jawaban Anda, ada begitu banyak komentar, kesalahpahaman, jawaban ... lagi pula saya memilih jawaban Anda karena Anda adalah orang pertama yang menyelesaikan apa yang saya minta terima kasih atas waktu Anda, Pak.
Mike
@ Mike Lol. Solusi lain berguna dalam hak mereka sendiri, jadi terima kasih atas penerimaan
mplungjan
Pavan's sama dalam sintaks ES6. Sulit dibaca tapi nyatanya sama. Suntingannya untuk membuatnya dibuat pada saat yang sama ketika saya menulis milik saya :)
mplungjan
8

Sementara tugas ini dapat diselesaikan dengan janji, aliran reaktif dan alat keren lainnya (hei, belum ada yang menyarankan menggunakan pekerja!), Itu juga dapat diselesaikan dengan aritmatika kecil.

Jadi Anda ingin waktu habis secara berurutan: 1s, yang sebelumnya +2s, yang sebelumnya +3s, dan sebagainya. Urutan ini adalah: 1, 3, 6, 10, 15 ... dan formulanya adalah a[n] = n * (n + 1) / 2. Mengetahui bahwa...

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
sumber
Matematikawan masih hidup !! :)
Bilal Siddiqui
5

Anda dapat mencoba menggunakan async / await (Janji), untuk membuat serialisasi kode Anda:

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
sumber
5

Butuh beberapa waktu untuk menguraikan pertanyaan Anda xD, tetapi apakah ini yang Anda inginkan?

Ini akan terus mengaktifkan console.log dengan i * 1000 delay setiap kali. jadi yang pertama kali akan menjadi 1 detik panjang (1 * 1000), selanjutnya akan menjadi 2 detik dan seterusnya.

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

Pavan Skipo
sumber
Misalnya, jika n = 5, maka saya ingin loop tunda 1 detik di iterasi 1. 2 detik dalam iterasi kedua, dan seterusnya .. penundaan akhir akan 5 detik.
Mike
ya ini akan menunda 1 detik untuk iterasi 1, 2 detik untuk 2 dan seterusnya, coba
Pavan Skipo
Uraian Anda tidak cocok dengan kode. Tapi itu berhasil
mplungjan
3

Loop tidak menunggu fungsi batas waktu selesai. Jadi, ketika loop dijalankan, jadwal peringatan Anda untuk setiap indeks.

Anda dapat menggunakan fungsi yang akan berjalan sesuai dengan indeks Anda tetapi dijadwalkan pada waktu yang sama. Anda dapat merasakan perbedaan 3 detik.

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

Gunakan panggilan rekursif bukan untuk 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);

elipsis
sumber
Misalnya, jika n = 5, maka saya ingin loop tunda 1 detik di iterasi 1. 2 detik dalam iterasi kedua, dan seterusnya .. penundaan akhir akan 5 detik.
Mike