Döngü İçin Aralık Süresini Dizin / Yineleme Numarasına Göre Dinamik Olarak Nasıl Değiştirebilirim?


12

Yorum yapamadığım için bu yazıyı yazmak zorunda kalıyorum. Tam olarak 1 saniye veya 1000 milisaniye geciktiren / bekleyen aşağıdaki kodu aldım -

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

Ancak, sabit 1000 milisaniye yerine i * 1000 saniyeyi nasıl geciktirebilirim, böylece bekleme yineleme numarasına bağlıdır?

Örneğin, n = 5 ise, döngü yineleme 1 yineleme 1 saniye istiyorum. Saniyede 2 saniye, vb. Son gecikme 5 saniye olacaktır.


2
Yani 9 zamanlayıcı yapmak ister misin? Eğer öyleyse, kodunuz istediğinizi yapacaktır. Tam olarak 3 saniye beklemez. Aslında, zamanlayıcılar asla kesin olmayacaktır.
Scott Marcus

1
sorunuzu anlamsız kılar
DanStarns

2
Kodunuzu bir kod alanında denedim: codepen.io/Connum/pen/BaaBMwW 3000 ms arayla 9 mesaj alıyorsunuz - eğer istediğiniz şey bu değilse (ancak sorunuzdan olduğu gibi geliyor), lütfen istediğiniz sonucun ne olduğunu belirtin dır-dir.
Constantin Groß

1
Sen setTimeout ilk etapta nasıl çalıştığını anlamak için görünmüyor - öyle değil , bir “gecikme”. Şu anda, uyarılarınızı 3 saniyelik aralıklarla alıyorsunuz , çünkü 3000'i zaten ile çarptınız i- bunu yapmadıysanız, tüm bu uyarıları aynı anda alırsınız .
04FS

3
Son cümlenizi kalınlaştırmak için soruyu düzenlemek, davanıza gerçekten yardımcı olmuyor. Şimdi size birden fazla yorumcu tarafından kodunuzun zaten istediğinizi yaptığını söylediler (ya da daha doğrusu, amaçladığınız sonuç değilse GERÇEKTEN ne istediğinizi net olarak bilmiyoruz).
Constantin Groß

Yanıtlar:


6

İşte hemen, sonra 1 saniye sonra, 2 saniye sonra, 3 saniye sonra vb. Gösterecek bir işlev. Özel matematik yok, vaat gerekli değil

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
Cevabınızı kaçırdığım için çok üzgünüm, çok fazla yorum, yanlış anlama, cevap vardı ... Her neyse, zaman ayırdığınız için teşekkür ettiğim şeyi çözen ilk kişi olarak cevabınızı seçiyorum efendim.
Mike

@Mike Lol. Diğer çözümler kendi başlarına faydalıdır, bu yüzden kabul için teşekkürler
mplungjan

Pavan, ES6 sözdiziminde aynıdır. Okuması daha zor ama aslında aynı. Bunu yapmak için yaptığı düzenleme, benim yazdığım gibi aynı zamanda yapıldı :)
mplungjan

8

Bu görev vaatler, reaktif akışlar ve diğer havalı araçlarla çözülebilse de (hey, kimse henüz işçi kullanmayı önermedi!), Aynı zamanda küçük bir aritmetik ile de çözülebilir.

Böylece bir sırayla zaman aşımı istiyorsunuz: 1s, önceki + 2s, önceki + 3s vb. Bu dizi: 1, 3, 6, 10, 15 ... ve formülü a[n] = n * (n + 1) / 2. Bilerek...

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


Matematikçiler hala hayatta !! :)
Bilal Siddiqui

5

Kodunuzu serileştirmek için async / await (Promises) kullanmayı deneyebilirsiniz:

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 sorunuzu deşifre etmem için biraz zamanımı aldı, ama istediğiniz şey bu mu?

Bu, her zaman i * 1000 gecikmesi ile console.log'u tetiklemeye devam edecektir . bu yüzden ilk kez 1 saniye uzunluğunda (1 * 1000) olacak, daha sonra 2 saniye olacak vb.

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


Örneğin, n = 5 ise, döngü yineleme 1 yineleme 1 saniye istiyorum. Saniyede 2 saniye, vb. Son gecikme 5 saniye olacaktır.
Mike

evet bu 1. iterasyon için 1 saniye, 2. ve 2. için 2 saniye geciktirecek, deneyin
Pavan Skipo

Açıklamanız kodla eşleşmiyor. Ama iş yapar
mplungjan

3

Döngü, zaman aşımı işlevinin tamamlanmasını beklemez. Bu nedenle, döngü çalıştığında her dizin için uyarınızı planlar.

Dizininize göre çalışacak, ancak aynı zamanda planlanan bir işlevi kullanabilirsiniz. 3 saniye farkını hissedebilirsiniz.

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

3

Döngü yerine özyinelemeli çağrılar kullanma

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


Örneğin, n = 5 ise, döngü yineleme 1 yineleme 1 saniye istiyorum. Saniyede 2 saniye, vb. Son gecikme 5 saniye olacaktır.
Mike
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.