İlk kez gecikmeden setInterval işlevini yürütün


341

setIntervalJavascript yöntemini yöntemi hemen uygulamak ve sonra zamanlayıcı ile yürütmek için yapılandırmanın bir yolu var


4
Doğal olarak değil. Bir functionkez aramayı deneyebilir ve daha sonrasetInterval()
Mrchief

Yanıtlar:


519

İşlevi ilk kez doğrudan kendiniz aramak en basit yöntemdir:

foo();
setInterval(foo, delay);

Bununla birlikte, kaçınmak için iyi nedenler vardır setInterval- özellikle bazı durumlarda bir sürü setIntervalolay gecikmeden birbiri ardına gelebilir. Başka bir neden, döngüyü durdurmak istiyorsanız, açıkça çağırmanız clearIntervalgerekir, bu da orijinal setIntervalçağrıdan döndürülen tanıtıcıyı hatırlamanız gerektiği anlamına gelir .

Bu nedenle alternatif bir yöntem, bunun yerine foosonraki aramalar için kendisini tetiklemektir setTimeout:

function foo() {
   // do stuff
   // ...

   // and schedule a repeat
   setTimeout(foo, delay);
}

// start the cycle
foo();

Bu, aramalar arasında en az bir aralık olmasını garanti eder delay. Ayrıca gerekirse döngüyü iptal etmeyi de kolaylaştırır - sadece setTimeoutdöngü sonlandırma koşulunuza ulaşıldığında aramazsınız.

Daha da iyisi, tüm bunları hemen yukarıdaki gibi çağıran ve döngüyü otomatik olarak başlatan işlevi yaratan hemen çağrılan bir işlev ifadesine sarılabilir :

(function foo() {
    ...
    setTimeout(foo, delay);
})();

Bu da işlevi tanımlar ve döngüyü tek seferde başlatır.


5
Neden tercih setTimeoutediyorsun?
Sanghyun Lee

19
@Sangdol çünkü işlenmemiş bırakılırsa zamanlayıcı olaylarının "yığılmamasını" sağlar. Bazı durumlarda, çok sayıda setIntervalolay birbiri ardına gecikmeden gelebilir.
Alnitak

8
Yorgunken yığına yazmana izin vermeyen bir tür test olmalı
James

3
setTimeoutYöntemi kullanırsam işlevi nasıl durdurabilirim ?
Gaurav Bhor

6
@DaveMunger hayır, çünkü gerçekten özyinelemeli değil - sadece "sözde özyinelemeli". Tarayıcı olay döngüsüne dönene kadar "özyinelemeli" çağrılar gerçekleşmez, bu noktada çağrı yığını tamamen açılır.
Alnitak

210

Seni doğru anladığımdan emin değilim, ama böyle bir şeyi kolayca yapabilirsin:

setInterval(function hello() {
  console.log('world');
  return hello;
}(), 5000);

Açıkçası bunu yapmanın birçok yolu var, ama bu benim düşünebileceğim en kısa yol.


16
Bu harika bir cevaptır çünkü derhal çalışan ve aynı zamanda kendini döndüren adlandırılmış bir işlevdir. Tam aradığım şey.
jmort253

41
Kesinlikle harika bir çözüm, ancak gelecekte okuyan insanlar için karışıklığa neden olması muhtemeldir.
Deepak Joy

4
Ona 'merhaba' adı vermenize gerek yok. Bunun yerine arguments.callee öğesini döndürebilir ve anonim bir işleve sahip olabilirsiniz
JochenJung

10
@JochenJung arguments.callee, ES5 katı modda mevcut değildir
Alnitak

3
Bu, diğer dillerden gelen çoğu yeni JS programcısını karıştıracak bir Javascript kodu türüdür. Şirketinizde çok fazla JS personeli yoksa ve iş güvenliği istiyorsanız, bunun gibi bir sürü şey yazın.
Ian

13

Aynı sorun nedeniyle bu soru üzerine tökezledim, ancak tam olarak gibi davranmanız gerekiyorsa, setInterval()ancak işlevin hemen başında çağrıldığı tek farkla cevapların hiçbiri yardımcı olmaz .

İşte bu sorunun çözümü:

function setIntervalImmediately(func, interval) {
  func();
  return setInterval(func, interval);
}

Bu çözümün avantajı:

  • mevcut kod kullanımı setIntervalikame ile kolayca uyarlanabilir
  • katı modda çalışır
  • mevcut adlandırılmış işlevler ve kapaklarla çalışır
  • yine de dönüş değerini kullanabilir ve clearInterval()daha sonra iletebilirsiniz

Misal:

// create 1 second interval with immediate execution
var myInterval = setIntervalImmediately( _ => {
        console.log('hello');
    }, 1000);

// clear interval after 4.5 seconds
setTimeout( _ => {
        clearInterval(myInterval);
    }, 4500);

Arsız olmak için, gerçekten kullanmanız gerekiyorsa setInterval, orijinali de değiştirebilirsiniz setInterval. Bu nedenle, mevcut kodunuzdan önce bunu eklerken herhangi bir kod değişikliği gerekmez:

var setIntervalOrig = setInterval;

setInterval = function(func, interval) {
    func();
    return setIntervalOrig(func, interval);
}

Yine de, yukarıda listelenen tüm avantajlar burada geçerlidir, ancak ikame gerekli değildir.


Bu çözümü çözüm yerine tercih ederim setTimeoutçünkü bir setIntervalnesne döndürür . Belki daha sonra kodda ve bu nedenle tanımlanmamış şimdiki zamanda olan fonksiyonları çağıran önlemek için, bir ilk işlev çağrısını sarın setTimeout: Böyle fonksiyonu setTimeout(function(){ func();},0);ilk fonksiyonu daha sonra da geçerli işlem döngüsü, sonra çağrılır hemen , ama daha fazla hata kanıtlandı.
pensan

8

Bu setInterval()davranışı sağlayan bir işlevi kapatabilirsiniz:

function instantGratification( fn, delay ) {
    fn();
    setInterval( fn, delay );
}

... sonra şu şekilde kullanın:

instantGratification( function() {
    console.log( 'invoked' );
}, 3000);

5
SetInterval'ın döndürdüğü şeyi döndürmeniz gerektiğini düşünüyorum. Çünkü aksi takdirde clearInterval'ı kullanamazsınız.
Henrik R

5

İhtiyacınız olursa oldukça güzelleştirmek için bir sarıcı:

(function() {
    var originalSetInterval = window.setInterval;

    window.setInterval = function(fn, delay, runImmediately) {
        if(runImmediately) fn();
        return originalSetInterval(fn, delay);
    };
})();

SetInterval öğesinin üçüncü bağımsız değişkenini true olarak ayarlayın; setInterval çağrıldıktan hemen sonra ilk kez çalıştırılır:

setInterval(function() { console.log("hello world"); }, 5000, true);

Veya üçüncü argümanı atlayın ve orijinal davranışını koruyun:

setInterval(function() { console.log("hello world"); }, 5000);

Bazı tarayıcılar , bu sarmalayıcının dikkate almadığı setInterval için ek argümanları destekler ; Bunların nadiren kullanıldığını düşünüyorum, ancak ihtiyacınız varsa bunu aklınızda bulundurun.


9
Özellikler değiştiğinde diğer mevcut kodları kırabileceğinden yerel tarayıcı işlevlerini geçersiz kılmak korkunçtur. Aslında, setInterval'ın şu anda daha fazla parametresi var: geliştirici.mozilla.org/en
US/docs/Web/API/WindowTimers/…

2

Çünkü birisinin thisbir ok işlevi gibi dışını içeri getirmesi gerekir .

(function f() {
    this.emit("...");
    setTimeout(f.bind(this), 1000);
}).bind(this)();

Yukarıdaki çöp üretmek sizi rahatsız ediyorsa, bunun yerine bir kapatma yapabilirsiniz.

(that => {
    (function f() {
        that.emit("...");
        setTimeout(f, 1000);
    })();
})(this);

Ya da belki kullanmayı düşünün dekoratör kodunuzu bağlı.@autobind


1

Fonksiyonları aşağıdaki sırayla çağırmayı önereceğim

var _timer = setInterval(foo, delay, params);
foo(params)

Belirli bir koşulda _timeristiyorsanız, foo'ya da geçebilirsiniz.clearInterval(_timer)

var _timer = setInterval(function() { foo(_timer, params) }, delay);
foo(_timer, params);

Bunu daha derinlemesine açıklayabilir misiniz?
Polyducks

zamanlayıcıyı ikinci aramadan ayarlarsınız, ilk defa fn'yi doğrudan ararsınız.
Jayant Varshney

1

İşte tüm karışıklık olmadan acemiler için basit bir sürüm. Sadece işlevi bildirir, çağırır, sonra aralığı başlatır. Bu kadar.

//Declare your function here
function My_Function(){
  console.log("foo");
}    

//Call the function first
My_Function();

//Set the interval
var interval = window.setInterval( My_Function, 500 );


1
İlk birkaç satırda kabul edilen cevap tam olarak bunu yapar. Bu cevap nasıl yeni bir şey ekliyor?
Dan Dascalescu

Kabul edilen cevap bunu yapmamaya devam ediyor. Kabul edilen cevaba cevabım neden hala geçerli bir yöntem olduğunu açıklıyor. OP özellikle ilk çağrısında setInterval işlevini çağırmayı ister, ancak kabul edilen yanıt setTimeout'un faydaları hakkında konuşmak için yönlendirilir.
Polyducks

0

Bu sorunu çözmek için işlevi sayfa yüklendikten sonra ilk kez çalıştırıyorum.

function foo(){ ... }

window.onload = function() {
   foo();
};

window.setInterval(function()
{
    foo(); 
}, 5000);

0

FirstInterval (tam açıklama, benim) adlı kullanışlı bir npm paketi var.

Buradaki örneklerin çoğu parametre işlemeyi içermez ve setIntervalherhangi bir büyük projedeki varsayılan davranışlarını değiştirmek kötüdür. Dokümanlardan:

Bu desen

setInterval(callback, 1000, p1, p2);
callback(p1, p2);

ile aynı

firstInterval(callback, 1000, p1, p2);

Tarayıcıda eski bir okul iseniz ve bağımlılığı istemiyorsanız , koddan kolayca kesip yapıştırın .


0

// YCombinator
function anonymous(fnc) {
  return function() {
    fnc.apply(fnc, arguments);
    return fnc;
  }
}

// Invoking the first time:
setInterval(anonymous(function() {
  console.log("bar");
})(), 4000);

// Not invoking the first time:
setInterval(anonymous(function() {
  console.log("foo");
}), 4000);
// Or simple:
setInterval(function() {
  console.log("baz");
}, 4000);

Tamam, bu çok karmaşık, o yüzden daha basit ifade edeyim:

function hello(status ) {    
  console.log('world', ++status.count);
  
  return status;
}

setInterval(hello, 5 * 1000, hello({ count: 0 }));


Bu büyük ölçüde aşırı tasarlanmış.
Polyducks

0

Çok küçük bir başlangıç ​​gecikme süresi (örn. 100) ayarlayabilir ve fonksiyon içinde istediğiniz gecikme süresine ayarlayabilirsiniz:

var delay = 100;

function foo() {
  console.log("Change initial delay-time to what you want.");
  delay = 12000;
  setTimeout(foo, delay);
}


-2

Standart setTimeout / setInterval, doğrudan 0'a ayarlasanız bile birkaç milisaniye hakkında minimum bir zaman aşımına sahip olduğundan, işlevinizin hemen eşzamansız çağrılmasıyla ilgili bir sorun vardır.

Chrome, Safari, Opera'da çalışan GERÇEK sıfır gecikmeli kod örneği

function setZeroTimeout(callback) {
var channel = new MessageChannel();
channel.port1.onmessage = callback;
channel.port2.postMessage('');
}

Daha fazla bilgiyi burada bulabilirsiniz

Ve ilk manuel aramadan sonra işlevinizle bir aralık oluşturabilirsiniz.


-10

aslında en hızlısı yapmak

interval = setInterval(myFunction(),45000)

bu benim işlevimi arayacak ve sonra her 45 saniyede bir agaian yapacak

interval = setInterval(myfunction, 45000)

ki bu onu çağırmaz, ama sadece planla


Bunu nereden aldın?
Ken Sharp

2
Bu sadece myFunction()kendi kendine dönerse çalışır . Bunun yerine, çağrılacak her işlevi değiştirmek , diğer yanıtların önerdiği gibi bir kez setIntervalsarmak için daha iyi bir yaklaşımdır setInterval.
Jens Wirth
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.