SetInterval aralığını çalışırken değiştirme


161

Belli sayıda yineleme için saniyenin her onda birini dizeyi değiştirmek için setInterval kullanan bir javascript işlevi yazdım.

function timer() {
    var section = document.getElementById('txt').value;
    var len = section.length;
    var rands = new Array();

    for (i=0; i<len; i++) {
        rands.push(Math.floor(Math.random()*len));
    };

    var counter = 0
    var interval = setInterval(function() {
        var letters = section.split('');
        for (j=0; j < len; j++) {
            if (counter < rands[j]) {
                letters[j] = Math.floor(Math.random()*9);
            };
        };
        document.getElementById('txt').value = letters.join('');
        counter++

        if (counter > rands.max()) {
            clearInterval(interval);
        }
    }, 100);
};

Aralığı belirli bir sayıya ayarlamak yerine, her sayaç çalıştığında sayacı temel alarak güncellemek istiyorum. Bunun yerine:

var interval = setInterval(function() { ... }, 100);

Şöyle bir şey olurdu:

var interval = setInterval(function() { ... }, 10*counter);

Ne yazık ki, bu işe yaramadı. "10 * sayaç" 0'a eşit gibi görünüyordu.

Peki, anonim işlev her çalıştığında aralığı nasıl ayarlayabilirim?

Yanıtlar:


107

setTimeout()Bunun yerine kullanın . Geri arama daha sonra bir sonraki zaman aşımını tetiklemekten sorumlu olacaktır, bu noktada zamanlamayı artırabilir veya başka bir şekilde değiştirebilirsiniz.

DÜZENLE

HERHANGİ BİR işlev çağrısı için "yavaşlayan" bir zaman aşımı uygulamak için kullanabileceğiniz genel bir işlev.

function setDeceleratingTimeout(callback, factor, times)
{
    var internalCallback = function(tick, counter) {
        return function() {
            if (--tick >= 0) {
                window.setTimeout(internalCallback, ++counter * factor);
                callback();
            }
        }
    }(times, 0);

    window.setTimeout(internalCallback, factor);
};

// console.log() requires firebug    
setDeceleratingTimeout(function(){ console.log('hi'); }, 10, 10);
setDeceleratingTimeout(function(){ console.log('bye'); }, 100, 10);

1
Geri arama ile, işlevin son satırı kendini bir setTimeout (..., newInterval) ile özyinelemeli olarak mı çağırıyor?
Marc

1
Öyle demek istediğini sanıyorum. Sadece denedim ve işe yarıyor gibi görünüyor. Teşekkürler beyler!
Joe Di Stefano

2
sadece 9 hi verir :) --tmuhtemelen t-- jsfiddle.net/albertjan/by5fd
albertjan

1
Bunu yinelemeli olarak yapmak times, çok büyükse yığın taşması hatası alma riskini almaz mısınız ?
André C. Andersen

4
Burada nitpicky olmak, ama söylemeliyim ki, bu kodu okumak oldukça zor. Sonraki satır ayraçlarını kullanacaksanız, en azından 4-8 boşluklu girinti kullanma veya asla 2 girintinin ötesine geçme nezaketine sahip olun. IMO bu sürümü okumak çok daha kolay. Ayrıca adının değiştirilmesine dikkat tetmek tick"t" için durmak gerekiyordu neyse konusunda benim en iyi tahmin olduğunu. toldukça kötü bir değişken adıdır.
Braden Best

124

Anonim bir işlev kullanabilirsiniz:

var counter = 10;
var myFunction = function(){
    clearInterval(interval);
    counter *= 10;
    interval = setInterval(myFunction, counter);
}
var interval = setInterval(myFunction, counter);

GÜNCELLEME: A. Wolff'un önerdiği gibi setTimeout, ihtiyaçtan kaçınmak için kullanın clearInterval.

var counter = 10;
var myFunction = function() {
    counter *= 10;
    setTimeout(myFunction, counter);
}
setTimeout(myFunction, counter);

5
Peki RozzA, cevabım 16 Eylül 11 ve 11, Kullanıcı 28958 22 Ağustos'ta yayınlanmıştır, bu yüzden "temsilcisi" teşekkür alacağım!
nick

12
Neden bir aralık kullanıyorsunuz, temizlemeye gerek kalmadan basit bir zaman aşımı daha iyi olur. ör .: jsfiddle.net/fgs5nwgn
A. Wolff

4
Sorunun bağlamına bağlı kalıyordum. setTimeout elbette çalışacak
nick

24

Bu soruyu seviyorum - içimde küçük bir zamanlayıcı nesnesine ilham verdi:

window.setVariableInterval = function(callbackFunc, timing) {
  var variableInterval = {
    interval: timing,
    callback: callbackFunc,
    stopped: false,
    runLoop: function() {
      if (variableInterval.stopped) return;
      var result = variableInterval.callback.call(variableInterval);
      if (typeof result == 'number')
      {
        if (result === 0) return;
        variableInterval.interval = result;
      }
      variableInterval.loop();
    },
    stop: function() {
      this.stopped = true;
      window.clearTimeout(this.timeout);
    },
    start: function() {
      this.stopped = false;
      return this.loop();
    },
    loop: function() {
      this.timeout = window.setTimeout(this.runLoop, this.interval);
      return this;
    }
  };

  return variableInterval.start();
};

Örnek kullanım

var vi = setVariableInterval(function() {
  // this is the variableInterval - so we can change/get the interval here:
  var interval = this.interval;

  // print it for the hell of it
  console.log(interval);

  // we can stop ourselves.
  if (interval>4000) this.stop();

  // we could return a new interval after doing something
  return interval + 100;
}, 100);  

// we can change the interval down here too
setTimeout(function() {
  vi.interval = 3500;
}, 1000);

// or tell it to start back up in a minute
setTimeout(function() {
  vi.interval = 100;
  vi.start();
}, 60000);

4
Teşekkürler - üzerinde çalıştığım benzer bir şey için beni doğru yönde ayarlayın.
Albay Sponsz

Basit ve etkili. Teşekkürler!
Jester

18

Orijinal posterle aynı sorum vardı, bunu bir çözüm olarak yaptım. Bu ne kadar verimli emin değilim ....

interval = 5000; // initial condition
var run = setInterval(request , interval); // start setInterval as "run"

    function request() { 

        console.log(interval); // firebug or chrome log
        clearInterval(run); // stop the setInterval()

         // dynamically change the run interval
        if(interval>200 ){
          interval = interval*.8;
        }else{
          interval = interval*1.2;
        }

        run = setInterval(request, interval); // start the setInterval()

    }

Ben aslında OP (ve benim) soruya cevap bu cevap daha iyi gibi . setTimeout, setInterval'in bu gecikmelerden etkilenmediği bir gecikmeye (% 100 işlemci kullanımı, diğer komut dosyaları vb.)
tabidir

8
setInterval@RozzA ile ilgili iddianızın yanlış olduğundan% 99 eminim - Hala diğer JavaScript'lerle aynı gecikmelere maruz kalıyor ve hemen hemen her tarayıcı da setInterval'ı 4ms'ye sıkıştırıyor. Bu ya da bununla ilgili bir gönderiye bağlantınız var mı?
gnarf

9

Bu benim yolu budur, ben setTimeout kullanın:

var timer = {
    running: false,
    iv: 5000,
    timeout: false,
    cb : function(){},
    start : function(cb,iv){
        var elm = this;
        clearInterval(this.timeout);
        this.running = true;
        if(cb) this.cb = cb;
        if(iv) this.iv = iv;
        this.timeout = setTimeout(function(){elm.execute(elm)}, this.iv);
    },
    execute : function(e){
        if(!e.running) return false;
        e.cb();
        e.start();
    },
    stop : function(){
        this.running = false;
    },
    set_interval : function(iv){
        clearInterval(this.timeout);
        this.start(false, iv);
    }
};

Kullanımı:

timer.start(function(){
    console.debug('go');
}, 2000);

timer.set_interval(500);

timer.stop();

+1, amaçlarım için biraz değiştirdim, böylece birden fazla değişken aralık kullanabilirim - jsfiddle.net/h70mzvdq
Dallas

Ayrıca set_intervalyeni aralık eskisinden daha küçük olmadığı sürece yeni bir yürütme başlatmak DEĞİL fonksiyonu değiştirildi ..if (iv < this.iv) { clearInterval(this.timeout); this.start(false, iv); } else { this.iv = iv; }
Dallas

9

Çok daha basit bir yol if, yenilenen işlevde bir deyime ve komutunuzu düzenli zaman aralıklarında yürütmek için bir kontrole sahip olmaktır. Aşağıdaki örnekte, her 2 saniyede bir uyarı çalıştırıyorum ve aralık ( intrv) dinamik olarak değiştirilebilir ...

var i=1;
var intrv=2; // << control this variable

var refreshId = setInterval(function() {
  if(!(i%intrv)) {
    alert('run!');
  }
  i++;
}, 1000);

Bu da benim kişisel favorim. küçük, basit, genişletilebilir.
adam mograbi

Ben uygulama olaylarına göre hızı sıfırlama olabilir yavaşlayan bir zamanlayıcı bir çözüm istedim; bu, basit ve mükemmel bir ihtiyaç duydu. Teşekkür ederim.
Andrew Brown

Havalı ama ihtiyaç duymadığınız anlarda aralıklarla ateşliyor ... ayrıca biraz okunamıyor. Bu nedenlerle ben şahsen setTimeout'u tercih ederim.
Kokodoko

4

Bu istediğiniz gibi başlatılabilir. zaman aşımı ben saatin üstünde tutmak için kullanılan yöntemdir.

Ben saatte bir kod bloğunu başlatmak için her saat ihtiyacım vardı. Bu, sunucu başlangıcında başlayacak ve aralığı saatlik olarak çalıştıracaktır. Temel olarak, başlangıç ​​çalışması aynı dakika içinde aralığa başlamaktır. Yani init'ten bir saniye içinde hemen sonra 5 saniyede bir çalıştırın.

var interval = 1000;
var timing =function(){
    var timer = setInterval(function(){
        console.log(interval);
        if(interval == 1000){ /*interval you dont want anymore or increment/decrement */
            interval = 3600000; /* Increment you do want for timer */
            clearInterval(timer);
            timing();
        }
    },interval);
}
timing();

Alternatif olarak, başlangıçta bir şeylerin olmasını ve sonsuza kadar belirli bir aralıkta olmasını istiyorsanız, setInterval ile aynı anda çağırabilirsiniz. Örneğin:

var this = function(){
 //do
}
setInterval(function(){
  this()
},3600000)
this()

Burada ilk kez ve sonra her saat çalışıyoruz.


3

Basit yanıt, önceden oluşturulmuş bir zamanlayıcı aralığını güncelleyememenizdir . (Yalnızca iki işlev vardır setInterval/setTimerve clearInterval/clearTimerbu nedenle bir seçeneğe sahip timerIdolmak yalnızca devre dışı bırakabilirsiniz.) Ancak bazı geçici çözümler yapabilirsiniz. Bu github deposuna bir göz atın .


2

SetIntervals hızımı da senkronize edemedim ve değiştiremedim ve bir soru göndermek üzereydim. Ama bence bir yol buldum. Kesinlikle geliştirilmeli çünkü ben bir acemiyim. Bu nedenle, yorumlarınızı / yorumlarınızı memnuniyetle okurdum.

<body onload="foo()">
<div id="count1">0</div>
<div id="count2">2nd counter is stopped</div>
<button onclick="speed0()">pause</button>
<button onclick="speedx(1)">normal speed</button>
<button onclick="speedx(2)">speed x2</button>
<button onclick="speedx(4)">speed x4</button>
<button onclick="startTimer2()">Start second timer</button>
</body>
<script>
var count1 = 0,
    count2 = 0,
    greenlight = new Boolean(0), //blocks 2nd counter
    speed = 1000,   //1second
    countingSpeed;
function foo(){
    countingSpeed = setInterval(function(){
        counter1();
        counter2();
    },speed);
}
function counter1(){
    count1++;
    document.getElementById("count1").innerHTML=count1;
}
function counter2(){
    if (greenlight != false) {
        count2++;
        document.getElementById("count2").innerHTML=count2;
    }
}
function startTimer2(){
    //while the button hasn't been clicked, greenlight boolean is false
    //thus, the 2nd timer is blocked
    greenlight = true;
    counter2();
    //counter2() is greenlighted
}

//these functions modify the speed of the counters
function speed0(){
    clearInterval(countingSpeed);
}
function speedx(a){
    clearInterval(countingSpeed);
    speed=1000/a;
    foo();
}
</script>

İsterseniz sayaçları sayfa, yüklenen konur kez artmaya başlaması counter1()ve counter2()de foo()daha öncecountingSpeed adı verilir. Aksi takdirde, speedyürütmeden önce milisaniye sürer . EDIT: Daha kısa cevap.


2
(function variableInterval() {
    //whatever needs to be done
    interval *= 2; //deal with your interval
    setTimeout(variableInterval, interval);
    //whatever needs to be done
})();

daha kısa olamaz


1

Javascript'te yeni başlayan biriyim ve önceki cevaplarda herhangi bir yardım bulamadım (ancak birçok iyi fikir).
Aşağıdaki bu kod parçası hızlanır (hızlanma> 1) veya yavaşlar (hızlanma <1). Umarım bazı insanlara yardımcı olabilir:

function accelerate(yourfunction, timer, refresh, acceleration) {
    var new_timer = timer / acceleration;
    var refresh_init = refresh;//save this user defined value
    if (refresh < new_timer ){//avoid reseting the interval before it has produced anything.
        refresh = new_timer + 1 ;
    };
    var lastInter = setInterval(yourfunction, new_timer);
    console.log("timer:", new_timer);
    function stopLastInter() {
        clearInterval(lastInter);
        accelerate(yourfunction, new_timer, refresh_init, acceleration);
        console.log("refresh:", refresh);
    };
    setTimeout(stopLastInter, refresh);
}

İle :

  • timer: ms cinsinden setInterval başlangıç ​​değeri (artan veya azalan)
  • refresh: yeni değerinin timerhesaplanmasından önceki süre . Bu adım uzunluğu
  • factor: eski ve sonraki timerdeğer arasındaki boşluk . Bu adım yüksekliği

1

Yeni işlev yap:

// set Time interval
$("3000,18000").Multitimeout();

jQuery.fn.extend({
    Multitimeout: function () {
        var res = this.selector.split(",");
        $.each(res, function (index, val) { setTimeout(function () { 
            //...Call function
            temp();
        }, val); });
        return true;
    }
});

function temp()
{
    alert();
}

1

Yavaşlayan / hızlanan aralık zamanlayıcı oluşturmanın başka bir yolu. Toplam süre aşılana kadar aralık bir faktörle çarpılır.

function setChangingInterval(callback, startInterval, factor, totalTime) {
    let remainingTime = totalTime;
    let interval = startInterval;

    const internalTimer = () => {
        remainingTime -= interval ;
        interval *= factor;
        if (remainingTime >= 0) {
            setTimeout(internalTimer, interval);
            callback();
        }
    };
    internalTimer();
}

0
var counter = 15;
var interval = setTimeout(function(){
    // your interval code here
    window.counter = dynamicValue;
    interval();
}, counter);

bana hata ver: Uncaught TypeError: interval is not a functionama bu çalıştı: jsfiddle.net/fgs5nwgn
Nabi KAZ

0

Yukarıdaki dahili geri çağrıdan esinlenerek , dakikalar içinde geri arama yapmak için bir işlev yaptım. Zaman aşımı 6000, 15 000, 30 000, 60 000 gibi aralıklara ayarlanırsa, aralıkların aralıklarını sistem saatinizin bir sonraki dakikasına tam geçişe senkronize olacak şekilde sürekli olarak uyarlar.

//Interval timer to trigger on even minute intervals
function setIntervalSynced(callback, intervalMs) {

    //Calculate time to next modulus timer event
    var betterInterval = function () {
        var d = new Date();
        var millis = (d.getMinutes() * 60 + d.getSeconds()) * 1000 + d.getMilliseconds();
        return intervalMs - millis % intervalMs;
    };

    //Internal callback
    var internalCallback = function () {
        return function () {
            setTimeout(internalCallback, betterInterval());
            callback();
        }
    }();

    //Initial call to start internal callback
    setTimeout(internalCallback, betterInterval());
};
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.