internet pencereler Android

Javascript, birden çok setinterval zamanlayıcısının aynı anda çalışmasını engeller. Javascript'te Zamanlayıcılar (setInterval, setTimeout)

JavaScript zaman aşımı, belirli bir zaman gecikmesinden sonra (milisaniye cinsinden) bir kod parçasını yürüten yerel bir javascript işlevidir. Bu, kullanıcı sayfanızda biraz zaman geçirdikten sonra bir açılır pencere görüntülemeniz gerektiğinde kullanışlı olabilir. Veya bir süre sonra imleci bir öğenin üzerine getirdiğinizde efektin başlamasını istiyorsunuz. Bu şekilde, kullanıcının yanlışlıkla üzerine gelmesi durumunda etkinin yanlışlıkla tetiklenmesini önleyebilirsiniz.

Basit setTimeout örneği

Bu işlevin etkisini göstermek için, düğmeye tıklandıktan iki saniye sonra bir açılır pencerenin göründüğü aşağıdaki demoya bir göz atmanızı öneririm.

Demoyu görüntüle

Sözdizimi

MDN belgeleri, setTimeout için aşağıdaki sözdizimini sağlar:

var timeoutID = window.setTimeout (fonk,); var timeoutID = window.setTimeout (kod,);

  • timeoutID, zamanlayıcıyı devre dışı bırakmak için clearTimeout () ile birlikte kullanılabilen sayısal bir kimliktir;
  • func, yürütülecek işlevdir;
  • kod ( alternatif sözdiziminde) - yürütülecek kod satırı;
  • gecikme - işlevin çalışacağı milisaniye cinsinden gecikme süresi. Varsayılan 0'dır.

setTimeout vs window.setTimeout

Yukarıdaki sözdizimi, window.setTimeout'u kullanır. Niye ya?

Aslında setTimeout ve window.setTimeout pratikte aynı işlevdir. Tek fark, ikinci ifadede, global pencere nesnesinin bir özelliği olarak setTimeout yöntemini kullanmamızdır.

Şahsen, bunun sadece kodu çok karmaşık hale getirdiğini düşünüyorum. Öncelik sırasına göre bulunabilen ve döndürülebilen alternatif bir JavaScript zaman aşımı yöntemi tanımlayacak olsaydık, daha da büyük sorunlarla karşılaşırdık.

Bu derste, pencere nesnesiyle uğraşmak istemiyorum, ancak genel olarak hangi sözdizimini kullanacağınıza siz karar verin.

kullanım örnekleri

Bu, işlevin adı olabilir:

patlama işlevi () (uyarı ("Boom!");) setTimeout (patlama, 2000);

Fonksiyona atıfta bulunan değişken:

var patlat = işlev () (uyarı ("Boom!"); setTimeout (patlama, 2000);

Veya anonim bir işlev:

setTimeout (işlev () (uyarı ("Boom!");), 2000);

  • Bu tür kodlar pek kabul görmez ve bu nedenle modernize etmek veya hata ayıklamak zor olacaktır;
  • Potansiyel bir güvenlik açığı olabilecek eval() yönteminin kullanımını içerir;
  • Bu yöntem diğerlerinden daha yavaştır çünkü çalışması gerekir. JavaScript yorumlayıcısı.

Ayrıca, kodu test etmek için JavaScript zaman aşımı uyarı yöntemini kullandığımızı unutmayın.

Parametreleri setTimout'a geçirme

İlk olarak ( ayrıca, çapraz tarayıcı) değişkeni olarak, setTimeout ile yürütülen geri çağırma işlevine parametreleri iletiyoruz.

Aşağıdaki örnekte, selamlama dizisinden rastgele bir selamlama çıkarıyoruz ve bunu setTimeout tarafından 1 saniye gecikmeyle yürütülen greet() işlevine parametre olarak iletiyoruz:

function selamlama (tebrik) (console.log (tebrik);) function getRandom (arr) (dönüş arr;) var selamlar = ["Merhaba", "Bonjour", "Guten Tag"], randomGreeting = getRandom (selamlar); setTimeout (fonksiyon () (selamlama (rastgele Selamlama);), 1000);

Demoyu görüntüle

alternatif yöntem

Bu makalenin başındaki söz diziminde, JavaScript timeout tarafından yürütülen geri çağırma işlevine parametreleri iletmek için kullanılabilecek başka bir yöntem vardır. Bu yöntem, gecikmeyi izleyen tüm parametrelerin çıktısını ifade eder.

Önceki örneği temel alarak şunları elde ederiz:

setTimeout (selamlama, 1000, randomTebrik);

Bu yöntem, geçirilen parametrelerin tanımsız olduğu IE 9 ve altındaki sürümlerde çalışmayacaktır. Ama bu sorunu çözmek için MDN'nin özel bir çoklu dolgusu vardır.

İlgili sorunlar ve "bu"

setTimeout tarafından yürütülen kod, onu çağıran fonksiyondan ayrı olarak çalışır. Bu nedenle bazı sorunlarla karşı karşıyayız, bu anahtar kelime bir çözüm olarak kullanılabilir.

var person = (firstName: "Jim", tanıt: function () (console.log ("Merhaba, I" m "+ this.firstName);)); person.introduce (); // Çıktılar: Merhaba, I" m Jim setTimeout (kişi.introduce, 50); // Çıktılar: Merhaba, ben tanımsızım

Bu sonucun nedeni, ilk örnekte bunun person nesnesine yol açması ve ikinci örnekte firstName özelliğine sahip olmayan global pencere nesnesine işaret etmesi gerçeğinde yatmaktadır.

Bu tutarsızlıktan kurtulmak için birkaç yöntem kullanabilirsiniz:

Bu değeri ayarlamaya zorla

Bu, bu anahtarın değeri olarak çağrıldığında belirli bir değer kullanan yeni bir işlev oluşturan bir yöntem olan bind () kullanılarak yapılabilir. Bizim durumumuzda, belirtilen kişi nesnesi. Bu bize sonuç olarak şunları verir:

setTimeout (kişi.introduce.bind (kişi), 50);

Not: bağlama, ECMAScript 5'te tanıtıldı; bu, yalnızca modern tarayıcılarda çalışacağı anlamına gelir. Diğerlerinde, uyguladığınızda bir çalışma zamanı hatası alırsınız. JavaScript "işlev zaman aşımı hatası".

Kitaplığı kullan

Birçok kitaplık, bu sorunu çözmek için gereken yerleşik işlevleri içerir. Örneğin, jQuery.proxy () yöntemi. Bir işlev alır ve her zaman belirli bir bağlamı kullanacağı yeni bir işlev döndürür. Bizim durumumuzda, bağlam şöyle olacaktır:

setTimeout ($.proxy (kişi.introduce, kişi), 50);

Demoyu görüntüle

Zamanlayıcıyı devre dışı bırak

setTimeout'un dönüş değeri, clearTimeout () işlevini kullanarak zamanlayıcıyı devre dışı bırakmak için kullanılabilen sayısal bir kimliktir:

var timer = setTimeout (myFunction, 3000); clearTimeout (zamanlayıcı);

Eylemde görelim. Bir sonraki örnekte, düğmesine tıklarsanız " Geri sayımı başlat”, Geri sayım başlar. Bittikten sonra, yavru kediler sahiplerini alacaklar. Ama eğer düğmeye basarsan " Geri sayımı durdur", JavaScript zaman aşımı durdurulacak ve sıfırlanacak.

Örneği görüntüle

özetleyelim

setTimeout asenkron bir işlevdir; bu, bu işleve gelen çağrının kuyruğa alındığı ve yalnızca yığındaki diğer tüm eylemler tamamlandıktan sonra yürütüleceği anlamına gelir. Diğer işlevlerle veya ayrı bir iş parçacığıyla aynı anda çalışamaz.

NS setAralık () Window ve Worker arabirimlerinde sunulan yöntem, her çağrı arasında sabit bir zaman gecikmesiyle art arda bir işlevi çağırır veya bir kod parçacığını yürütür. Aralığı benzersiz olarak tanımlayan bir aralık kimliği döndürür, böylece daha sonra clearInterval () öğesini çağırarak kaldırabilirsiniz. Bu yöntem WindowOrWorkerGlobalScope karışımı tarafından tanımlanır.

Sözdizimi

var intervalID = kapsam.setInterval ( işlev, gecikme, [arg1, arg2, ...]); var intervalID = kapsam.setInterval ( kod, gecikme);

parametreler

func Her gecikme milisaniyesinde yürütülecek bir işlev. İşlev herhangi bir bağımsız değişken iletilmez ve herhangi bir dönüş değeri beklenmez. kod İsteğe bağlı bir sözdizimi, her gecikme milisaniyesinde derlenen ve yürütülen bir işlev yerine bir dize eklemenize olanak tanır. Bu sözdizimi tavsiye edilmez eval () kullanımını bir güvenlik riski yapan aynı nedenlerle. gecikme Milisaniye (saniyenin binde biri) cinsinden süre, zamanlayıcı belirtilen işlev veya kodun yürütülmesi arasında gecikmelidir. İzin verilen gecikme değerleri aralığıyla ilgili ayrıntılar için aşağıya bakın. arg1, ..., argN Tarafından belirtilen işleve iletilen İsteğe Bağlı Ek bağımsız değişkenler işlev zamanlayıcı sona erdiğinde.

Not: İlk sözdiziminde setInterval () öğesine ek bağımsız değişkenler iletmek, Internet Explorer 9 ve önceki sürümlerde çalışmaz. Bu işlevi o tarayıcıda etkinleştirmek istiyorsanız, bir çoklu dolgu kullanmanız gerekir (bölüme bakın).

Geri dönüş değeri

Döndürülen intervalID, setInterval() çağrısı tarafından oluşturulan zamanlayıcıyı tanımlayan sıfır olmayan sayısal bir değerdir; bu değer, zaman aşımını iptal etmek için iletilebilir.

setInterval() ve setTimeout() öğelerinin aynı kimlik havuzunu paylaştığını ve clearInterval() ve clearTimeout() öğelerinin teknik olarak birbirinin yerine kullanılabileceğini bilmek yararlı olabilir. Ancak netlik için, kodunuzu korurken karışıklığı önlemek için her zaman bunları eşleştirmeye çalışmalısınız.

Not: Gecikme bağımsız değişkeni, işaretli bir 32 bit tam sayıya dönüştürülür. Bu, IDL'de işaretli bir tamsayı olarak belirtildiğinden, gecikmeyi etkin bir şekilde 2147483647 ms ile sınırlar.

Örnekler

Örnek 1: Temel sözdizimi

Aşağıdaki örnek, setInterval() "s temel sözdizimini gösterir.

Var intervalID = window.setInterval (myCallback, 500, "Parametre 1", "Parametre 2"); function myCallback (a, b) (// Buradaki kodunuz // Parametreler tamamen isteğe bağlıdır.console.log (a); console.log (b);)

Örnek 2: Değişen iki renk

Aşağıdaki örnek, Durdur düğmesine basılana kadar saniyede bir flashtext () işlevini çağırır.

setInterval / clearInterval örneği

Selam Dünya

Örnek 3: Daktilo simülasyonu

Aşağıdaki örnek, belirli bir seçici grubuyla eşleşen içeriği önce temizleyerek ve ardından yavaşça NodeList'e yazarak daktiloyu simüle eder.

JavaScript Daktilo - MDN Örneği

Mozilla Developer Network tarafından CopyLeft 2012

[ Oynamak | Duraklat | sonlandırmak ]

Fringilla lectus imperdiet'te Vivamus blandit massa ut metus mattis. Proin ac ante a felis ornare araç. Arka arkaya lacus vitae eros convallis ut mollis magna pellentesque. Lacus ultricies vitae facilisis nisi fringilla'da Pellentesque placerat enim. Tincidunt tincidunt tincidunt.

JavaScript Daktilo

Lorem ipsum dolor sit amet, conectetur adipiscing elit. Nullam ultrices dolor ac dolor imperdiet ullamcorper. Suspendisse quam libero, luctus auctor mollis sed, maleuada condimentum magna. Ante tellus'ta Quisque, placerat est'de. Pellentesque sakini morbi tristique senectus ve netus ve maleuada şöhretleri ac turpis egestas. Çok iyiyim, çok iyiyim. Etiam sit amet ligula quis urna auctor imperdiet nec faucibus ante. Mauris vel consectetur dolor. Nunc eget elit eget velit pulvinar fringilla conectetur aliquam purus. Curabitur convallis, justo posuere porta egestas, velit erat ornare tortor, non viverra justo diam eget arcu. Phasellus adipiscing fermentum nibh ac commodo. Nam turpis nunc, hendrerit vitae, volutpat non ipsum.

Phasellus ac nisl lorem:

Duis lobortis sapien quis nisl luctus porttitor. Tempor semper libero'da, eu tincidunt dolor eleifend sit amet. Ut nec velit in dolor tincidunt rhoncus non-diam. Morbi auctor ornare orci, euismod olmayan felis gravida nec. Curabitur elementum nisi ve eros rutrum nec blandit diam placerat. Aenean tincidunt risus ut nisi conectetur cursus. Ut özgeçmiş quam elit. Donec dignissim quam tempor consequat içinde tahmin. Aliquam aliquam diam non felis convallis suscipit. Sıfır kolaylık. Donec lacus risus, dignissim ve fringilla et, egestas vel eros. Duis maleuada accumsan dui, fringilla mauris bibStartum quis adresinde. Cras adipiscing ultricies fermentum. Praesent bibStartum condimentum feugiat.

Nam faucibus, ligula eu fringilla pulvinar, lectus tellus iaculis nunc, vitae scelerisque metus leo non metus. Proin mattis lobortis lobortis. Quisque accumsan faucibus erat, vel varius tortor ultricies ac. Lorem ipsum dolor sit amet, conectetur adipiscing elit. Sed nec libero nunc. Nullam tortor nunc, elementum a consectetur et, ultrices eu orci. Lorem ipsum dolor sit amet, conectetur adipiscing elit. Pellentesque bir nisl eu sem vehicula egestas.

Geri arama argümanları

Daha önce tartışıldığı gibi, Internet Explorer sürüm 9 ve altı, setTimeout () veya setInterval () içindeki geri çağırma işlevine bağımsız değişkenlerin iletilmesini desteklemez. Devamındaki IE'ye özgü kodu, bu sınırlamanın üstesinden gelmek için bir yöntem gösterir. Kullanmak için komut dosyanızın en üstüne aşağıdaki kodu eklemeniz yeterlidir.

/ * \ | * | |* | İsteğe bağlı bağımsız değişkenlerin |* | javascript zamanlayıcılarının geri çağırma işlevleri (HTML5 standart sözdizimi) .. setInterval |* | https: // site / Kullanıcı: fusionchess |* | |* | Sözdizimi: |* | var timeoutID = window.setTimeout (işlev, gecikme [, arg1, arg2, ...]); |* | var timeoutID = window.setTimeout (kod, gecikme); |* | var intervalID = window.setInterval (işlev, gecikme [, arg1, arg2, ...]); |* | var intervalID = window.setInterval (kod, gecikme); |* | \ * / if (document.all &&! window.setTimeout.isPolyfill) (var __nativeST__ = window.setTimeout; window.setTimeout = işlev (vCallback, nDelay / *, argümanToPass1, argümanToPass2, vb. * /) (var aArgs = Array .prototype.slice.call (argümanlar, 2); __nativeST __ döndür ) if (document.all &&! window.setInterval.isPolyfill) (var __nativeSI__ = window.setInterval; window.setInterval = function (vCallback, nDelay / *, argümanToPass1, argümanToPass2, vb. * /) (var aArgs = Array.prototype) . dilim.call (argümanlar, 2); return __nativeSI __ (İşlev?in vCallback örneği? function () (vCallback.apply (null, aArgs);): vCallback, nDelay);); window.setInterval.isPolyfill = true;)

Başka bir olasılık da geri aramanızı aramak için anonim bir işlev kullanmaktır, ancak bu çözüm biraz daha pahalıdır. Örnek:

Var intervalID = setInterval (işlev () (myFunc ("bir", "iki", "üç");), 1000); var intervalID = setInterval (işlev (arg1) () .bind (tanımsız, 10), 1000);

Etkin olmayan sekmeler

Gecko 5.0 gerektirir (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)

Gecko 5.0'dan (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2) başlayarak, etkin olmayan sekmelerde aralıklar saniyede bir defadan fazla olmayacak şekilde sıkıştırılır.

"Bu" sorunu

setInterval () veya başka bir işleve bir yöntem ilettiğinizde, bu değer yanlış olarak çağrılır. Bu sorun JavaScript referansında ayrıntılı olarak açıklanmıştır.

Açıklama

setInterval () tarafından yürütülen kod, çağrıldığı işlevden ayrı bir yürütme bağlamında çalışır. Sonuç olarak, çağrılan işlev için this anahtar sözcüğü, pencere (veya global) nesnesine ayarlanır, setTimeout adlı işlevin bu değeri ile aynı değildir. Aşağıdaki örneğe bakın ( setInterval () yerine setTimeout () kullanır - aslında sorun her iki zamanlayıcı için de aynıdır):

MyArray = ["sıfır", "bir", "iki"]; myArray.myMethod = function (sProperty) (uyarı (arguments.length> 0? bu: bu); myArray.myMethod(); // "sıfır, bir, iki" yazdırır myArray.myMethod (1); // "bir" yazdırır setTimeout (myArray.myMethod, 1000); // 1 saniye sonra "" yazdırır setTimeout (myArray.myMethod, 1500, "1"); // 1,5 saniye sonra "tanımsız" yazdırır // "bu" nesneyi .call ile geçirmek "işe yaramaz // çünkü bu setTimeout'un içindeki bunun değerini değiştirir // myArray içinde bunun değerini değiştirmek istediğimizde .myMethod // aslında, setTimeout kodu bunun pencere nesnesi olmasını beklediğinden bir hata olacaktır: setTimeout.call (myArray, myArray.myMethod, 2000); // hata: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: WrappedNative prototip nesnesinde geçersiz işlem " setTimeout.call (myArray, myArray.myMethod, 2500, 2); // aynı hata

Gördüğünüz gibi, bu nesneyi eski JavaScript'teki geri çağırma işlevine iletmenin bir yolu yoktur.

Olası bir çözüm

"Bu" sorunu çözmenin olası bir yolu, iki yerel setTimeout () veya setInterval () global işlevini iki işlevle değiştirmektir. yerli olmayan Function.prototype.call yöntemi aracılığıyla çağrılmalarını sağlayanlar. Aşağıdaki örnek olası bir değiştirmeyi gösterir:

// JavaScript zamanlayıcıları aracılığıyla "bu" nesnenin geçişini etkinleştirin var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval; window.setTimeout = işlev (vCallback, nDelay / *, argümanToPass1, argümanToPass2, vb. * /) (var oThis = this, aArgs = Array.prototype.slice.call (argümanlar, 2); return __nativeST __ (İşlev?in vCallback örneği? function () (vCallback.apply (oThis, aArgs);): vCallback, nDelay);); window.setInterval = fonksiyon (vCallback, nDelay / *, argümanToPass1, argümanToPass2, vb. * /) (var oThis = this, aArgs = Array.prototype.slice.call (argümanlar, 2); return __nativeSI __ (İşlev?in vCallback örneği? function () (vCallback.apply (oThis, aArgs);): vCallback, nDelay););

Bu iki değiştirme, aynı zamanda, IE'deki zamanlayıcıların geri çağırma işlevlerine isteğe bağlı argümanların HTML5 standart geçişini sağlar. Yani olarak kullanılabilirler standart dışı ayrıca polyfill'ler. için bkz. standart uyumluçoklu dolgu.

Yeni özellik testi:

MyArray = ["sıfır", "bir", "iki"]; myArray.myMethod = function (sProperty) (uyarı (arguments.length> 0? bu: bu); setTimeout (uyarı, 1500, "Merhaba dünya!"); // setTimeout ve setInterval standart kullanımı korunur, ancak ... setTimeout.call (myArray, myArray.myMethod, 2000); // 2 saniye sonra "sıfır, bir, iki" yazdırır setTimeout.call (myArray, myArray.myMethod, 2500, 2); // 2,5 saniye sonra "iki" yazdırır

Daha karmaşık ama yine de modüler bir versiyonu için ( arka plan programı) bkz. JavaScript Daemons Management. Bu daha karmaşık sürüm, büyük ve ölçeklenebilir bir yöntem koleksiyonundan başka bir şey değildir. arka plan programı yapıcı. Ancak arka plan programı yapıcının kendisi bir klondan başka bir şey değildir Mini Daemon için ek bir destek ile içinde ve başlangıçta somutlaştırılması sırasında bildirilebilir işlevler şeytan . Böylece Mini Daemonçerçeve basit animasyonlar için önerilen yol olmaya devam ediyor, Çünkü arka plan programı yöntemleri koleksiyonu olmadan, esasen onun bir klonudur.

minidaemon.js

/ * \ | * | |* | :: MiniDaemon :: | * | |* | Revizyon # 2 - 26 Eylül 2014.setInterval |* | https: // site / Kullanıcı: fusionchess |* | https://github.com/madmurphy/minidaemon.js |* | |* | Bu çerçeve, GNU Kısıtlı Genel Kamu Lisansı, sürüm 3 veya üzeri altında yayımlanmıştır. |* | http://www.gnu.org/licenses/lgpl-3.0.html |* | \ * / function MiniDaemon (oOwner, fTask, nRate, nLen) (if (! (bu && MiniDaemon'un bu örneği)) (dönüş;) if (arguments.length< 2) { throw new TypeError("MiniDaemon - not enough arguments"); } if (oOwner) { this.owner = oOwner; } this.task = fTask; if (isFinite(nRate) && nRate >0) (this.rate = Math.floor (nRate);) if (nLen> 0) (this.length = Math.floor (nLen);)) MiniDaemon.prototype.owner = null; MiniDaemon.prototype.task = boş; MiniDaemon.prototype.rate = 100; MiniDaemon.prototype.length = Sonsuz; / * Bu özellikler salt okunur olmalıdır * / MiniDaemon.prototype.SESSION = -1; MiniDaemon.prototype.INDEX = 0; MiniDaemon.prototype.PAUSED = doğru; MiniDaemon.prototype.BACKW = doğru; / * Genel yöntemler * / MiniDaemon.forceCall = fonksiyon (oDmn) (oDmn.INDEX + = oDmn.BACKW? -1: 1; if (oDmn.task.call (oDmn.owner, oDmn.INDEX, oDmn.length, oDmn) .BACKW) === false || oDmn.isAtEnd ()) (oDmn.pause (); false döndür;) true döndür;); / * Örnek yöntemleri * / MiniDaemon.prototype.isAtEnd = function () (bunu döndür.BACKW? IsFinite (this.length) && this.INDEX< 1: this.INDEX + 1 >this.uzunluk; ); MiniDaemon.prototype.synchronize = function () (if (this.PAUSED) (dönüş;) clearInterval (this.SESSION);this.SESSION = setInterval (MiniDaemon.forceCall, this.rate, this); MiniDaemon.prototype.pause = işlev () (clearInterval (this.SESSION); this.PAUSED = true;); MiniDaemon.prototype.start = function (bReverse) (var bBackw = Boolean (bReverse); if (this.BACKW === bBackw && (this.isAtEnd () ||! This.PAUSED)) (dönüş;) this.BACKW = bBackw; this.PAUSED = false; this.synchronize (););

MiniDaemon, argümanları geri çağırma işlevine iletir. Doğal olarak bu özelliği desteklemeyen tarayıcılarla üzerinde çalışmak istiyorsanız, yukarıda önerilen yöntemlerden birini kullanın.

Sözdizimi

var myDaemon = new MiniDaemon ( bu nesne, geri aramak[ , oran [, uzunluk]]);

Açıklama

Kullanım notları

setInterval () işlevi, animasyonlar gibi tekrar tekrar yürütülen işlevler için bir gecikme ayarlamak için yaygın olarak kullanılır. WindowOrWorkerGlobalScope.clearInterval () kullanarak aralığı iptal edebilirsiniz.

Eğer fonksiyonunuzun çağrılmasını istiyorsanız bir Zamanlar belirtilen gecikmeden sonra kullanın.

Gecikme kısıtlamaları

Aralıkların iç içe olması mümkündür; yani setInterval () için geri arama, sırayla, setInterval () öğesini çağırarak, birincisi hala devam ediyor olsa bile, başka bir aralığın çalışmasına başlayabilir. performans için, aralıklar beş düzeyin ötesinde iç içe yerleştirildiğinde, tarayıcı otomatik olarak aralık için minimum 4 ms'lik bir değer uygular. setInterval () öğesine derinlemesine iç içe çağrılarda 4 ms'den küçük bir değer belirleme girişimleri 4 ms'ye sabitlenir.

Tarayıcılar, bazı durumlarda aralık için daha da katı minimum değerler uygulayabilir, ancak bunların yaygın olmaması gerekir. Geri aramaya yapılan aramalar arasında geçen gerçek sürenin, verilen gecikmeden daha uzun olabileceğini de unutmayın; örnekler için WindowOrWorkerGlobalScope.setTimeout () içinde belirtilenden daha uzun gecikmelerin nedenleri bölümüne bakın.

Yürütme süresinin aralık frekansından daha kısa olduğundan emin olun

Mantığınızın yürütülmesinin aralık süresinden daha uzun sürmesi olasılığı varsa, setTimeout () kullanarak yinelemeli olarak adlandırılmış bir işlevi çağırmanız önerilir. Örneğin, uzak bir sunucuyu her 5 saniyede bir yoklamak için setInterval () kullanılıyorsa, ağ gecikmesi, yanıt vermeyen bir sunucu ve bir dizi başka sorun, isteğin ayrılan sürede tamamlanmasını engelleyebilir. Bu nedenle, kendinizi "mutlaka sırayla geri gelmeyecek" sıraya alınmış XHR istekleriyle bulabilirsiniz.

  • İtibaren:
  • Kayıtlı: 2014.07.08
  • Gönderiler: 3,896
  • Seviyor: 497

Konu: JavaScript'te kullanmak daha iyi olan SetTimeOut ve SetInterval?

Kodu düzenli aralıklarla birden çok kez çalıştırmak için işlev setAralık... Ancak, birçok dezavantajı vardır, özellikle farklı tarayıcılarda farklı davranışlar.

İlk fark, bir sonraki başlatma için zamanlayıcı ayarlandığındaki farktır. Küçük bir test oluşturalım: Bir önceki çalıştırmanın başından ve sonundan geçen süreyi ölçeceğiz.

var d1 = yeni Tarih (), d2 = yeni Tarih (); setInterval (işlev () (var d = yeni Tarih (); document.body.innerHTML + = (d - d1) + "" + (d - d2) + "
"; // Fonksiyonun başına bir etiket koyun d1 = new Date(); while (new Date() - d1< 200); // ничего не делаем 200 миллисекунд // И в конце функции d2 = new Date(); }, 1000);

Çıktı, ikinci satırdan başlayarak bilgilendirici olacaktır.

Firefox, Opera, Safari ve Chrome'da durum benzer olacaktır: ilk sayı yaklaşık 1000'e eşit, ikincisi - 200 daha az olacaktır. Fark sadece değerler aralığında olacaktır. Chrome ve Opera'daki en küçük varyasyon.

2 tarafından yanıtla PunBB (PunBB 2017.06.08 16:45 tarafından düzenlendi)

  • İtibaren: Moskova, Sovkhoznay 3, apt. 98
  • Kayıtlı: 2014.07.08
  • Gönderiler: 3,896
  • Seviyor: 497

Daha az fark edilen ve yeniden üretilmesi daha zor olan, ancak bazen çok fazla soruna neden olabilen bir diğer fark, sistem zamanındaki değişikliklere karşı dirençtir. Bir sonraki testi çalıştırırsanız

setInterval (işlev () (document.body.innerHTML = Math.random ();), 500);

Başladıktan sonra, sistem saatini bir dakika geriye ayarlayın, ardından Firefox ve Safari tarayıcılarında sayı değişikliği duraklayacak ve bir dakika sonra tekrar başlayacaktır. Elbette, sistem saatinin manuel olarak çevrilmesi son derece nadir bir durumdur, ancak birçok sistem, zamanı İnternet'teki sunucularla otomatik olarak senkronize edecek şekilde yapılandırılmıştır, bu nedenle bazı durumlarda bu faktör göz ardı edilemez.

setInterval işlevinin bir başka küçük dezavantajı, eylemini durdurabilmek için tanımlayıcısını bir yerde hatırlamanız gerekmesidir, bu her zaman uygun değildir.

3 tarafından yanıtla PunBB

  • İtibaren: Moskova, Sovkhoznay 3, apt. 98
  • Kayıtlı: 2014.07.08
  • Gönderiler: 3,896
  • Seviyor: 497

Re: SetTimeOut ve SetInterval, JavaScript'te kullanmak daha mı iyi?

setInterval'in listelenen dezavantajlarından kurtulmak için birden fazla setTimeout kullanabilirsiniz.

setInterval için önemli bir alternatif özyinelemeli setTimeout'tur:

/ ** yerine: var timerId = setInterval (function () (alert ("tick");), 2000); * / var timerId = setTimeout (işlev kene () (alert ("tık"); timerId = setTimeout (tık, 2000);), 2000);

Yukarıdaki kodda, bir sonraki yürütme, bir öncekinin bitiminden hemen sonra planlanmıştır.

Özyinelemeli setTimeout, setInterval'den daha esnek bir zamanlama yöntemidir, çünkü bir sonraki yürütmeye kadar geçen süre, geçerli olanın sonuçlarına bağlı olarak farklı şekilde programlanabilir.

Örneğin, her 5 saniyede bir sunucuyu yeni veriler için yoklayan bir hizmetimiz var. Sunucu aşırı yüklenirse, yoklama aralığını 10, 20, 60 saniyeye çıkarabilirsiniz ... Ve her şey normalleştiğinde geri döndürün.

İşlemciyi düzenli olarak yükleyen görevlerimiz varsa, bunların yürütülmesi için harcanan süreyi tahmin edebilir ve bir sonraki başlatmayı er ya da geç planlayabiliriz.

4 tarafından yanıtla PunBB

  • İtibaren: Moskova, Sovkhoznay 3, apt. 98
  • Kayıtlı: 2014.07.08
  • Gönderiler: 3,896
  • Seviyor: 497

Re: SetTimeOut ve SetInterval, JavaScript'te kullanmak daha mı iyi?

Özyinelemeli setTimeout, çağrılar arasında bir duraklamayı garanti eder, setInterval bunu sağlamaz.

İki kodu karşılaştıralım. İlki setInterval kullanır:

var i = 1; setInterval (işlev () (işlev (i);), 100);

İkincisi özyinelemeli bir setTimeout kullanır:

var i = 1; setTimeout (işlev çalıştırma () (işlev (i); setTimeout (çalıştır, 100);), 100);

setInterval ile dahili zamanlayıcı tam olarak her 100ms'de bir tetiklenir ve func (i) öğesini çağırır:

setInterval ile func çağrıları arasındaki gerçek duraklama, kodda belirtilenden daha azdır!

Bu doğaldır, çünkü işlevin çalışma süresi hiçbir şekilde dikkate alınmaz, aralığın bir kısmını "yer".

Ayrıca func'un beklediğimizden daha karmaşık olduğu ve yürütülmesinin 100 ms'den uzun sürdüğü de mümkündür.

Bu durumda, tercüman işlevin tamamlanmasını bekleyecek, ardından zamanlayıcıyı kontrol edecek ve setInterval'i çağırma zamanı geldiyse (veya geçtiyse), bir sonraki çağrı hemen gerçekleşecektir.

İşlev, setInterval duraklamasından daha uzun sürerse, aramalar kesintisiz olarak gerçekleşir.

5 tarafından yanıtla sempai

  • İtibaren: Kudüs
  • Kayıtlı: 2015.06.02
  • Gönderiler: 958
  • Seviyor: 274

Re: SetTimeOut ve SetInterval, JavaScript'te kullanmak daha mı iyi?

Her şey eldeki göreve bağlıdır. Başlangıçta, zamanlayıcıyı bir kez başlatmak için SetTimeOut ve döngüyü başlatmak için SetInterval kullanılır. Ancak her iki işlev de komut dosyaları arasında döngü yapmak için kullanılabilir, örneğin SetTimeOut işlevinde özyinelemeli olarak çalıştırılırsa, SetInterval'e benzer pratik bir şekilde hareket edecektir.

SetInterval'in şu anda dezavantajı, betiğin (fonksiyonun) kendisinin yürütme süresini dikkate almamasıdır ve örneğin, onu ağır istekler için kullanırsanız, aralık süresi önemli ölçüde azalır ve farklı tarayıcılarda farklılık gösterebilir.

Ancak tekrar ediyorum, işlev veya istek en aza indirilirse, son kullanıcının farkı hissetmesi olası değildir.
Bu nedenle, ne kullanılacağına herkes kendisi karar verir.

Kaynak: http://learn.javascript.ru/settimeout-setinterval

Hemen hemen tüm JavaScript uygulamalarında, belirli bir süre sonra bir işlev çağrısı planlamanıza olanak tanıyan dahili bir zamanlayıcı vardır.

Özellikle bu özellik tarayıcılarda ve Node.JS sunucusunda desteklenir.

setZaman aşımı

Sözdizimi:

var timerId = setTimeout (işlev / kod, gecikme [, arg1, arg2 ...])

Seçenekler:

  • işlev / kod
    • Yürütülecek bir işlev veya kod satırı.
    • Dize uyumluluk için desteklenir ve önerilmez.
  • gecikme
    • Milisaniye cinsinden gecikme, 1000 milisaniye 1 saniyeye eşittir.
  • arg1, arg2 ...
    • İşleve geçmek için argümanlar. IE9-'de desteklenmez.
    • İşlev, gecikme parametresinde belirtilen süreden sonra yürütülecektir.

Örneğin, aşağıdaki kod bir saniye sonra uyarı ("Merhaba") arayacaktır:

işlev işlevi ()(uyarı ("Merhaba"));) setTimeout (işlev, 1000);

İlk argüman bir dizge ise, yorumlayıcı bu dizgeden isimsiz bir işlev yaratır.

Yani, böyle bir kayıt tam olarak aynı şekilde çalışır:

SetTimeout ("uyarı (" Merhaba ")", 1000);

Bunun yerine anonim işlevleri kullanın:

Zamanaşımı Ayarla ( işlev ()(uyarı ("Merhaba")), 1000);

İşlev parametreleri ve bağlam

Tüm modern tarayıcılarda, IE10 göz önünde bulundurularak setTimeout, işlev parametrelerini belirlemenize olanak tanır.

Aşağıdaki örnekte, IE9- dışında her yerde "Merhaba, ben Vasya" görüntülenecektir:

işlev sayHi (kim)(uyarı ("Merhaba, ben" + kim);) setTimeout (sayHi, 1000, "Vasya");

... Ancak, çoğu durumda eski IE için desteğe ihtiyacımız var ve bu, argümanları belirtmenize izin vermiyor. Bu nedenle, onları iletmek için çağrı anonim bir işleve sarılır:

işlev sayHi (kim)(uyarı ("Merhaba, ben" + kim);) setTimeout ( işlev ()(sayHi ("Vasya")), 1000);

setTimeout üzerinden çağrı yapmak bu bağlamı geçmez.

Özellikle, bir nesnenin yöntemini setTimeout aracılığıyla çağırmak genel bağlamda çalışacaktır. Bu yanlış sonuçlara yol açabilir.

Örneğin, bir saniye sonra user.sayHi () öğesini çağıralım:

işlev Kullanıcı (id) işlev ()(uyarı (bu .id);); ) var user = new User (12345); setTimeout (user.sayHi, 1000); // 12345 bekleniyor, ancak "tanımsız" yazdırılacak

setTimeout global bağlamda user.sayHi işlevini çalıştıracağından, nesneye bu yolla erişemez.

Başka bir deyişle, setTimeout'a yapılan bu iki çağrı aynı şeyi yapar:

// (1) bir satır setTimeout (user.sayHi, 1000); // (2) iki satırda aynı şey var func = user.sayHi; setTimeout (işlev, 1000);

Neyse ki, bu sorun da bir ara işlev yaratılarak kolayca çözülür:

işlev Kullanıcı (id)(bu .id = id; bu .sayHi = işlev ()(uyarı (bu .id);); ) var user = new User (12345); setZaman aşımı ( işlev ()(user.sayHi ();), 1000);

Sarıcı işlevi, tarayıcılar arası geçiş argümanları ve yürütme bağlamını depolamak için kullanılır.

Yürütmeyi iptal et

setTimeout işlevi, bir eylemi iptal etmek için kullanılabilecek bir timerId döndürür.

Sözdizimi:

ClearTimeout (zamanlayıcı kimliği)

Aşağıdaki örnekte, bir zaman aşımı belirledik ve ardından sildik (fikrimizi değiştirdik). Sonuç olarak hiçbir şey olmuyor.

var timerId = setTimeout ( işlev ()(uyarı (1)), 1000); clearTimeout (timerId);

setAralık

setInterval yöntemi, setTimeout'a benzer bir sözdizimine sahiptir.

var timerId = setInterval (işlev / kod, gecikme [, arg1, arg2 ...])

Argümanların anlamı aynıdır. Ancak setTimeout'tan farklı olarak, işlevin yürütülmesini bir kez değil, belirli bir zaman aralığında düzenli olarak tekrarlar. Aşağıdakileri arayarak yürütmeyi durdurabilirsiniz:

ClearInterval (zamanlayıcı kimliği)

Aşağıdaki örnek, başlangıçta, siz Durdur düğmesine tıklayana kadar her iki saniyede bir mesaj görüntüler:

<giriş tipi = "düğme" onclick = "clearInterval (zamanlayıcı)" değer = "(! DİL: Dur" > !} <komut dosyası> var i = 1; var timer = setInterval ( işlev ()(uyarı (i ++)), 2000);komut dosyası>

setInterval'de aramaları sıraya alma ve üst üste bindirme

setInterval (işlev, gecikme) çağrılması, belirtilen zaman aralığından sonra yürütülecek işlevi koyar. Ama burada bir incelik var.

Aslında, aramalar arasındaki duraklama, belirtilen aralıktan daha azdır.

Örneğin, setInterval (işlev () (işlev (i ++))), 100'ü alın. Her 100 ms'de bir func yürütür ve her seferinde sayacı artırır.

Aşağıdaki resimde kırmızı blok, func'un yürütme zamanıdır. Bloklar arasındaki süre, fonksiyonun başlamaları arasındaki süredir ve ayarlanan gecikmeden daha azdır!

Diğer bir deyişle, tarayıcı, işlevin yürütme süresini hesaba katmadan, her 100 ms'de bir işlevin düzgün bir şekilde başlatılmasını başlatır.

Bir işlevin yürütülmesinin gecikmeden daha uzun sürdüğü görülür. Örneğin, işlev karmaşıktır ve gecikme süresi küçüktür. Veya işlev, yürütme dizisini engelleyen uyarı / onay / istem ifadeleri içerir. Bu durumda ilginç şeyler başlar.

Tarayıcı meşgul olduğu için işlev başlatılamazsa, tarayıcı boş kalır kalmaz kuyruğa alınır ve yürütülür.

Aşağıdaki resim, yürütülmesi uzun zaman alan bir işlev için neler olduğunu göstermektedir.

setInterval tarafından başlatılan bir işlev çağrısı kuyruğa eklenir ve mümkün olduğunda hemen gerçekleşir:

Fonksiyonun ikinci çalıştırması, birincinin bitiminden hemen sonra gerçekleşir:

Yürütme birden fazla sıraya alınmaz.

Bir işlevin yürütülmesi birkaç programlanmış yürütmeden daha uzun sürerse, yine de bir kez kuyruğa girecektir. Yani lansmanların "birikimi" yoktur.

Aşağıdaki resimde setInterval, işlevi 200ms'de yürütmeye çalışır ve çağrıyı kuyruğa alır. 300ms ve 400ms'de zamanlayıcı tekrar uyanır, ancak hiçbir şey olmaz.

setInterval (işlev, gecikme) çağrısı, yürütmeler arasında gerçek bir gecikmeyi garanti etmez.

Gerçek gecikmenin belirtilenden daha büyük veya daha az olduğu zamanlar vardır. Genel olarak, en azından bir tür gecikme olacağı bir gerçek değildir.

Yuvalanmış setTimeout'un tekrarı

Sadece düzenli tekrarın gerekli olmadığı, aynı zamanda başlatmalar arasında bir gecikmenin gerekli olduğu durumlarda, fonksiyon her çalıştırıldığında setTimeout yeniden ayarlanmalıdır.

Aşağıda, aralarında 2 saniyelik aralıklarla bir uyarı yayan bir örnek verilmiştir.

<input type = "button" onclick = "clearTimeout (zamanlayıcı)" değer = "(! LANG: Dur" > !} <komut dosyası> var i = 1; var timer = setTimeout ( fonksiyon çalıştırma ()(uyarı (i ++); zamanlayıcı = setTimeout (çalıştır, 2000);), 2000);komut dosyası>

Yürütme zaman çizelgesindeki çalıştırmalar arasında sabit gecikmeler olacaktır. 100ms gecikme için örnek:

Minimum zamanlayıcı gecikmesi

Tarayıcı zamanlayıcısı, mümkün olan en düşük gecikmeye sahiptir. Modern tarayıcılarda yaklaşık sıfırdan 4 ms'ye kadar değişir. Daha eskilerde daha yüksek olabilir ve 15ms'ye ulaşabilir.

Standart olarak, minimum gecikme 4 ms'dir. Yani setTimeout (.., 1) ile setTimeout (.., 4) arasında fark yoktur.

Sıfır gecikmeli setTimeout ve setInterval davranışları tarayıcıya özeldir.

  1. Opera'da setTimeout (.., 0), setTimeout (.., 4) ile aynıdır. setTimeout'tan (.., 2) daha az sıklıkta çalışır. Bu, bu tarayıcının bir özelliğidir.
  2. Internet Explorer'da sıfır gecikmeli setInterval (.., 0) çalışmayacaktır. Bu özellikle setInterval için geçerlidir, yani. setTimeout (.., 0) iyi çalışıyor.

Gerçek yanıt frekansı

Tetikleme çok daha az sıklıkta olabilir.Bazı durumlarda gecikme 4ms değil 30ms hatta 1000ms olabilir.

Çoğu tarayıcı (öncelikle masaüstü), sekme etkin olmasa bile setTimeout / setInterval'i yürütmeye devam eder. Aynı zamanda, birkaçı (Chrome, FF, IE10) minimum zamanlayıcı frekansını saniyede 1 defaya kadar düşürür. "Arka plan" sekmesinde bir zamanlayıcının tetikleneceği, ancak nadiren tetikleneceği ortaya çıktı.

Bir dizüstü bilgisayarda pil gücüyle çalışırken - tarayıcılar, kodu daha az sıklıkta yürütmek ve pil gücünden tasarruf etmek için frekansı da düşürebilir. IE özellikle bunun için ünlüdür. Azaltma, ayarlara bağlı olarak birkaç kata kadar olabilir. İşlemci yükü çok ağırsa, JavaScript zamanlayıcıları zamanında işleyemeyebilir. Bu, bazı setInterval çalıştırmalarını atlayacaktır.

Sonuç: 4ms frekansı tarafından yönlendirilmelisiniz, ancak buna güvenmemelisiniz.

Aralıkların konsola çıktısı Çağrılar arasındaki aralıkları sayan kod şuna benzer:

var timeMark = new Date; setZaman aşımı ( işlev git ()(var diff = new Date - timeMark; // konsola sayfa yerine başka bir gecikme yazdır konsol .log (fark); // en sondaki zamanı hatırla, // aramalar arasındaki gecikmeyi tam olarak ölçmek için timeMark = yeni Tarih; setTimeout (git, 100); ), 100 );

setTimeout (işlev, 0) hilesi

Bu numara, JavaScript hack'lerinin yıllıklarına girmeye değer.

Geçerli betiğin bitiminden sonra çalıştırmak istiyorsanız, işlev setTimeout (func, 0) içine sarılır.

Buradaki nokta, setTimeout'un hiçbir zaman bir işlevi hemen yürütmemesidir. Sadece uygulanmasını planlıyor. Ancak JavaScript yorumlayıcısı, yalnızca mevcut komut dosyasının yürütülmesinden sonra planlanan işlevleri yürütmeye başlayacaktır.

Standart olarak setTimeout zaten 0 gecikmeli bir işlevi çalıştıramaz.Daha önce de söylediğimiz gibi gecikme genellikle 4ms olur. Ancak buradaki en önemli şey, yürütmenin her durumda mevcut kodun yürütülmesinden sonra olacağıdır.

Örneğin:

var sonuç; fonksiyon gösterSonuç ()(uyarı (sonuç);) setTimeout (showResult, 0); sonuç = 2 * 2; // 4 yazdıracak

Toplam

setInterval (işlev, gecikme) ve setTimeout (işlev, gecikme) yöntemleri, işlevin düzenli olarak / gecikme milisaniye sonra bir kez çalıştırılmasına izin verir.

Her iki yöntem de zamanlayıcı kimliğini döndürür. clearInterval / clearTimeout'u çağırarak yürütmeyi durdurmak için kullanılır.

| | setAralık | setZaman aşımı | || ----------- | ---------- | | zamanlama | Kesinlikle bir zamanlayıcıda bir arama devam ediyor. Tercüman meşgulse, bir arama kuyruğa girer. Fonksiyonun yürütme süresi dikkate alınmaz, bu nedenle bir çalışmanın sonundan diğerinin başlangıcına kadar olan zaman aralığı farklı olabilir. | Yürütmeler arasında sabit bir duraklamanın gerekli olduğu durumlarda setInterval yerine setTimeout'a özyinelemeli çağrı kullanılır. | | Gecikme | Minimum gecikme: 4ms. | Minimum gecikme: 4ms. | | Tarayıcı Özellikleri | Gecikme 0 IE'de çalışmıyor | Opera'da sıfır gecikme süresi 4 ms'ye eşittir, standart olmayan 1 ms, 2 ms ve 3 ms dahil olmak üzere diğer gecikmeler doğru bir şekilde işlenir. |

Komut dosyası dillerinde programlamada, programın yürütülmesini bir süre askıya almak ve ardından çalışmaya devam etmek için periyodik olarak bir duraklama oluşturmak gerekir. Örneğin, VBS ve PHP betiklerinde aşağıdaki yöntemler mümkündür:

VBS: wscript.sleep 1500 (1,5 saniye durun)

PHP: uyku (10); (10 saniye durun)

Bu tür duraklamalar sırasında, çalışma zamanı sistemi (PHP veya VBS) hiçbir şey yapmamak... Javascript'te böyle bir şeyi sezgisel olarak kullanmaya çalışan bir geliştirici tatsız bir şekilde şaşıracaktır. Javascript'te bir duraklama oluşturmaya çalışırken tipik bir hata şöyle görünür:

badtest () işlevi ((var i = 1; i için)< 10; i++) { window.setTimeout("document.getElementById("test1").value += " + i, 900) } }

Döngüden geçerken sıra bir sonraki rakamı çizmeye geldiğinde, setZaman aşımı Javascript'i dürüstçe durduracak, 0,9 saniye bekleyecek, gerekli sayıyı giriş alanının sonuna ekleyecek ve ardından çalışmaya devam edecektir. Ama aslında öyle değil: setAralık ve setZaman aşımı Javascript'te yalnızca parantez içinde belirtilen eylem (veya işlev) geciktirilir. Örneğimizde aşağıdakiler gerçekleşecektir:

  1. ben = 1;
  2. giriş alanına "1" sayısını eklemeyi 0,9 saniye erteleyin;
  3. hemen bu sorunu ayarladıktan sonra döngü devam eder: i = 2;
  4. giriş alanına "2" sayısını eklemeyi 0.9 saniye erteleyin;

Hemenörneğin, 1 ms (yani, 900 ms'ye kıyasla kıyaslanamayacak kadar küçük) anlamına gelir: döngü işini neredeyse anında gerçekleştirecek ve aynı anda birkaç bekleyen görev yaratacaktır. Bu, bekleyen tüm "çizim" görevlerinin, yeni sayıların eklenmesi arasında duraklama olmaksızın hemen hemen aynı anda tamamlanacağı anlamına gelir. Döngü başlar; her şey 0,9 saniye boyunca donar; ve shirrr - tüm sayılar arka arkaya çekilir.

Ve böyle bir durumda nasıl başvurulur? setZaman aşımı? Karmaşık. işlevi çağırmak zorunda tekrarlı(fonksiyonun içinden, aynı fonksiyon) ve bu işlemin sonsuz olmaması için durma koşulunu ayarlayın (örneğin, yazdırılan sayının değeri):

İşlev iyi testi () (eğer (i< 9) { document.getElementById("test2").value += ++i window.setTimeout("welltest()", 400) } }

Ve başka bir değişken ben işlevin dışında başlatılmalıdır - örneğin, şöyle:

Artık her şey olması gerektiği gibi çalışıyor (gecikme süresini 0,9 sn'den 0,4 sn'ye düşürdük). Ancak bu tür görevler için değil kullanmak daha mantıklı setZaman aşımı a setAralık(bunun iki işlev gerektirmesine rağmen):

En iyi test () işlevi (window.i = 0 window.timer1 = window.setInterval ("draw ()", 400)) işlevi draw () (document.getElementById ("test3"). Value + = ++ i if (i > = 9) clearInterval (window.timer1))

Javascirpt yönteminin özelliği setAralık"kendiliğinden" geçmediği için özel bir yöntemle durdurulması gerekir. clearInterval... Tam olarak neyin durdurulacağını netleştirmek için, ertelenen eylem görevine özel bir tanımlayıcı atanır - bir zamanlayıcı: window.timer1 = window.setInterval (...).

Tanımlayıcılar, yöntem tarafından oluşturulan görevlere de atanabilir. setZaman aşımı... Tüm zamanlayıcı kimlikleri birbirinden farklı olmalıdır (geçerli tarayıcı penceresinde benzersiz). Ardından, pencerede ertelenmiş eylemleri kullanan birkaç farklı görev oluşturabilirsiniz ve bu görevler paralel olarak yürütülür (bilgisayar yeterli kaynağa sahipse aynı anda gibi), bu temelde PHP veya VBS'de imkansızdır.

İşte aynı anda çalışan birkaç Javascript zamanlayıcısı olan bir sayfa örneği: setinterval.htm (setinterval.js dosyasındaki Javascript fonksiyonları). Tüm sayfa zamanlayıcıların çalışması (menü hariç) Esc tuşuna basılarak durdurulabilir. Tüm örnek zamanlayıcılar "doğal" (soyut değil) ben ++) geri sayım - zaman veya mesafe. Tüm "saatler" özel olarak senkronize değildir (açıklık için). Mesafe bazlı zamanlayıcılar "gösterge"de ve açılır (açılır) menüde kullanılır.

Aşağıya doğru açılan menü

Açılır menümüz aslında açılır menüdür ("başlığın" altından): nasıl çıktığını görmek için öğeler arasında boşluklar vardır. Beklenmedik bir şekilde, farklı uzunluklardaki listeler için eşit derecede yumuşak bir çıkış yapamadığımız ortaya çıktı - muhtemelen bilgisayarın düşük performansı nedeniyle (AMD Athlon 999 MHz).

Güzellik ve uyum için farklı menü öğelerinin listelerinin aynı anda görünmesi gerektiği oldukça açıktır. Yani, daha uzun listeler daha hızlı, daha kısa olanlar - daha düşük bir oranda çıkmalıdır. Bunun şu şekilde uygulanabileceği anlaşılıyor:

  1. Toplam "kalkış" süresini örneğin 200 ms olarak belirledik.
  2. Açılır listenin yüksekliği 20 pikselse, onu 10 ms'de bir piksel aşağı hareket ettirebileceğimiz açıktır - ve ardından 200 ms'de tüm liste açılır.
  3. Açılır menü 40 piksel yüksekliğindeyse, aynı anda sığdırmak için onu 5 ms'de bir piksel aşağı taşımamız gerekir.

Bu mantığa göre, eğer açılır liste 200 piksel yüksekliğindeyse, 1 ms'de her seferinde bir piksel aşağı hareket ettirmeliyiz. Ancak bu hız bilgisayarımızda çalışmıyor - tarayıcının listenin yeni konumunu bir milisaniyede çizmek için zamanı yok. Evet. Javascript'in saymak için zamanı var (sayılacak ne var?), Ve tarayıcının (Firefox) görüntülemek için zamanı yok. Web için tipik bir durum.

Bu nedenle, sadece koltuk değneği yardımıyla menüden çıkma süresini aşağı yukarı eşitlemek mümkündür ve bunun daha hızlı bir bilgisayarda nasıl çalışacağı hala belirsizdir. Ama en yavaş olana güvenmeliyiz, değil mi? Algoritma (bilgisayarın hızını hesaba katmadan) şöyle bir şey olur:

  1. Listenin toplam çıkış süresini belirledik: time = 224 (ms).
  2. Döngüde bir aralık için minimum süreyi belirledik: gecikme = 3 (ms).
  3. Listeyi taşımak için minimum adımı ayarlayın: offset = 1 (px).
  4. Tüm bunları listenin yüksekliğine bağlı olarak değiştiriyoruz: 1) gecikme (aralık) süresini yükseklikle ters orantılı ve toplam süre ile doğru orantılı olarak artırın (224 yükseklikte, katsayı 1'dir); 2) Yükseklik 40 pikselden fazla ise, minimum adımı yükseklikle orantılı olarak artırın. Sabit "40", en yavaş bilgisayar için deneysel olarak elde edilir. Pentium 4 CPU 2.53GHz bilgisayardaki testler, tam olarak aynı sayıyı gösterdi - 40. Aksi takdirde, zamanlayıcılar çılgına döner, listeler adım adım ilerler.

Şimdi listeler az ya da çok yayılıyor. Aşağı yukarı benzer bir süre için. setinterval.htm sayfasında.

Ve işte Bru-bıyık:

Slide_do işlevi (obj, maxtop, offset) (if (getTopLeft (obj) .top)< maxtop) { obj.style.top = getTopLeft(obj).top + offset } else { if (obj && obj.timer1) { clearInterval(obj.timer1) obj.timer1 = null } } }

Menüden iç içe listeleri çıkaran işlevin kendisi de gördüğünüz gibi çok basit. Sadece bu satır gibi bir şeyle çalıştırmak için kalır:

Ts.timer1 = setInterval (fonksiyon () (slide_do (ts, maxtop, offset)), gecikme)

Peki, başlamadan önce, tüm bu maxtop ve offset'i hesaplayın ve ayrıca listeyi mintop konumuna getirin. "Ön" işlevi ne yapar? kaymak () 40 satır boyutunda. Ve hep birlikte - setinterval.js dosyasında. Evet ve bu saçmalık, dahil edilmiş bir stil sayfası olmadan çalışmaz.