Jquery interval za izvršavanje funkcije. Primjeri jQuery funkcije setTimeout(). Prosljeđivanje parametara u setTimout

💖 Sviđa li vam se? Podijelite vezu sa svojim prijateljima
  • Iz:
  • Registriran: 08.07.2014
  • Postovi: 3.896
  • Sviđa mi se: 497
Tema: SetTimeOut i SetInterval, što je bolje koristiti u JavaScriptu?

Funkcija setInterval dizajnirana je za pokretanje koda više puta u pravilnim intervalima. Međutim, ima niz nedostataka, uglavnom drugačije ponašanje u različitim preglednicima.

Prva razlika je razlika u vremenu u kojem je mjerač vremena postavljen za sljedeće pokretanje. Napravimo mali test: izmjerit ćemo koliko je vremena prošlo od početka prethodnog pokretanja i od njegovog završetka.

var d1 = novi datum(), d2 = novi datum(); setInterval(function() ( var d = new Date(); document.body.innerHTML += (d - d1) + " " + (d - d2) + "
"; // Stavite oznaku na početak funkcije d1 = new Date(); while (new Date() - d1< 200); // ничего не делаем 200 миллисекунд // И в конце функции d2 = new Date(); }, 1000);

Izlaz će biti informativan počevši od drugog retka.

U Firefoxu, Operi, Safariju i Chromeu situacija će biti slična: prvi broj će biti približno jednak 1000, drugi - 200 manji. Jedina će razlika biti u širenju vrijednosti. Najmanja razlika je u Chromeu i Operi.

2 Odgovor PunBB-a (uredio PunBB 8.6.2017. 16:45)
  • Od: Moskva, Sovkhoznay 3, apt. 98
  • Registriran: 08.07.2014
  • Postovi: 3.896
  • Sviđa mi se: 497

Još jedna razlika koja je manje uočljiva i teže ju je reproducirati, ali ponekad može uzrokovati mnogo problema, jest otpornost na promjene vremena sustava. Ako pokrenete sljedeći test

setInterval(function() (document.body.innerHTML = Math.random(); ), 500);

I nakon pokretanja, vratite sistemsko vrijeme unazad minutu, a zatim će se u preglednicima Firefox i Safari promjena brojeva zaustaviti, a nakon minute će se ponovno pokrenuti. Naravno, ručno prevođenje sistemskog vremena iznimno je rijetka situacija, ali mnogi su sustavi konfigurirani za automatsku sinkronizaciju vremena s poslužiteljima na Internetu, tako da se u nekim situacijama ovaj faktor ne može zanemariti.

Još jedan mali nedostatak funkcije setInterval je da, kako biste mogli zaustaviti njezino djelovanje, morate negdje zapamtiti njegov identifikator, što nije uvijek zgodno.

3 Odgovor PunBB-a
  • Od: Moskva, Sovkhoznay 3, apt. 98
  • Registriran: 08.07.2014
  • Postovi: 3.896
  • Sviđa mi se: 497
Re: SetTimeOut i SetInterval, što je bolje koristiti u JavaScriptu?

Da biste se riješili navedenih nedostataka setIntervala, možete koristiti višestruki setTimeout.

Važna alternativa setIntervalu je rekurzivni setTimeout:

/** umjesto: var timerId = setInterval(function() ( alert("tick"); ), 2000); */ var timerId = setTimeout(funkcija tick() ( alert("tick"); timerId = setTimeout(tick, 2000); ), 2000);

U gornjem kodu, sljedeće izvršenje zakazano je odmah nakon završetka prethodnog.

Rekurzivni setTimeout je fleksibilnija metoda mjerenja vremena od setIntervala, budući da se vrijeme do sljedećeg izvršenja može drugačije rasporediti, ovisno o rezultatima trenutnog.

Na primjer, imamo uslugu koja provjerava poslužitelj za nove podatke svakih 5 sekundi. Ako je poslužitelj preopterećen, možete povećati interval prozivanja na 10, 20, 60 sekundi... I onda ga vratiti kada se sve vrati u normalu.

Ako redovito pokrećemo CPU-intenzivne zadatke, tada možemo procijeniti vrijeme utrošeno na njihovo izvršenje i planirati sljedeće pokretanje ranije ili kasnije.

4 Odgovor PunBB-a
  • Od: Moskva, Sovkhoznay 3, apt. 98
  • Registriran: 08.07.2014
  • Postovi: 3.896
  • Sviđa mi se: 497
Re: SetTimeOut i SetInterval, što je bolje koristiti u JavaScriptu?

Rekurzivni setTimeout jamči pauzu između poziva, setInterval ne.

Usporedimo dva koda. Prvi koristi setInterval:

var i = 1; setInterval(funkcija() (func(i); ), 100);

Drugi koristi rekurzivni setTimeout:

var i = 1; setTimeout(funkcija run() ( func(i); setTimeout(run, 100); ), 100);

Uz setInterval, interni mjerač vremena aktivirat će se točno svakih 100 ms i pozvati funkciju (i):

Prava pauza između func poziva sa setInterval je manja nego što je navedeno u kodu!

To je prirodno, jer se vrijeme rada funkcije ni na koji način ne uzima u obzir, ono "pojede" dio intervala.

Također je moguće da se func pokazao složenijim nego što smo očekivali i da je za izvršenje trebalo više od 100 ms.

U ovom slučaju, tumač će čekati da funkcija završi, zatim provjeriti mjerač vremena i, ako je vrijeme za pozivanje setIntervala već došlo (ili prošlo), tada će se sljedeći poziv dogoditi odmah.

Ako funkcija radi dulje od pauze setInterval, tada će se pozivi dogoditi bez ikakvih prekida.

5 Odgovorio sempai
  • Iz: Jeruzalema
  • Registriran: 02.06.2015
  • Postovi: 958
  • Sviđa mi se: 274
Re: SetTimeOut i SetInterval, što je bolje koristiti u JavaScriptu?

Sve ovisi o zadatku koji se radi. U početku se SetTimeOut koristi za jednokratno pokretanje mjerača vremena, a SetInterval za pokretanje petlje. Ali obje funkcije se mogu koristiti za cikličko pokretanje skripti; ako ih, na primjer, pokrenete rekurzivno u funkciji SetTimeOut, tada će djelovati gotovo slično kao SetInterval.

Nedostatak SetIntervala trenutno je što ne uzima u obzir vrijeme izvršenja same skripte (funkcije), a ako ga npr. koristite za teške upite, tada će vrijeme intervala biti značajno smanjeno, a mogu se razlikovati u različitim preglednicima.

Ali opet, ako je funkcija ili zahtjev minimiziran, tada krajnji korisnik vjerojatno neće osjetiti razliku.
Stoga, što će koristiti, svatko odlučuje za sebe.

Izuzetno je važno razumjeti kako oni rade JavaScript mjerači vremena. Često njihovo ponašanje ne odgovara našem intuitivnom razumijevanju višenitnosti, a to je zbog činjenice da se u stvarnosti izvršavaju u jednoj niti. Pogledajmo četiri funkcije pomoću kojih možemo upravljati mjeračima vremena:

  • var id = setTimeout(fn, kašnjenje); - Stvara jednostavan mjerač vremena koji će pozvati zadanu funkciju nakon zadane odgode. Funkcija vraća jedinstveni ID s kojim se tajmer može pauzirati.
  • var id = setInterval(fn, kašnjenje); - Slično setTimeoutu, ali kontinuirano poziva funkciju u zadanom intervalu (dok se ne zaustavi).
  • clearInterval(id);, clearTimeout(id); - Prihvaća ID tajmera (koji vraća jedna od gore opisanih funkcija) i zaustavlja izvršenje povratnog poziva"a.
Glavna ideja koju treba uzeti u obzir je da točnost razdoblja odgode timera nije zajamčena. Za početak, preglednik izvršava sve asinkrone JavaScript događaje u jednoj niti (kao što su klikovi mišem ili tajmeri) i to samo u trenutku kada je taj događaj na redu. To najbolje pokazuje sljedeći dijagram:

Ima dosta informacija koje treba uzeti u obzir u ovoj slici, ali njeno razumijevanje će vam dati dublje razumijevanje kako JavaScript asinkronija funkcionira. Ovaj grafikon prikazuje vrijeme okomito u milisekundama, plavi blokovi prikazuju blokove JavaScript koda koji su izvršeni. Na primjer, prvi blok se izvršava u prosjeku za 18 ms, klik mišem blokira izvršenje za oko 11 ms, itd.

JavaScript može izvršiti samo jedan dio koda (zbog jednonitne prirode izvršavanja), od kojih svaki blokira izvršavanje drugih asinkronih događaja. To znači da kada se dogodi asinkroni događaj (kao što je klik mišem, poziv mjerača vremena ili završetak XMLHttp zahtjeva), on se dodaje u red čekanja i izvršava kasnije (implementacija ovisi o pregledniku, naravno, ali složimo se da nazovite to "red čekanja") .

Za početak, zamislimo da se dva mjerača vremena pokreću unutar JavaScript bloka: setTimeout s odgodom od 10 ms i setInterval s istom odgodom. Ovisno o tome kada se mjerač vremena pokrene, aktivirat će se u trenutku kada još nismo dovršili prvi blok koda. Međutim, imajte na umu da se ne aktivira odmah (ovo nije moguće zbog jednostrukog navoja). Umjesto toga, odgođena funkcija stavlja se u red čekanja i izvršava u sljedećem dostupnom trenutku.

Također, tijekom izvođenja prvog JavaScript bloka dolazi do klika mišem. Rukovatelj za ovaj asinkroni događaj (a on je asinkroni jer ga ne možemo predvidjeti) ne može se izvršiti izravno u ovom trenutku, tako da također završava u redu čekanja, poput mjerača vremena.

Nakon što je prvi blok JavaScript koda izvršen, preglednik postavlja pitanje: "Što čeka na izvršenje?" U ovom slučaju rukovatelj klikom miša i mjerač vremena su u stanju čekanja. Preglednik odabire jedan od njih (obavljač klikova) i izvršava ga. Mjerač vremena će čekati sljedeći raspoloživi dio vremena u redu čekanja za izvršavanje.

Imajte na umu da dok se rukovatelj klikom miša izvršava, aktivira se prvi interval povratnog poziva. Baš kao i tajmer-callback, bit će stavljen u red čekanja. Međutim, imajte na umu da će interval biti uklonjen iz reda čekanja kada se ponovno aktivira (dok je pokrenut povratni poziv timera). Kad bi se svaki interval-callback" stavio na čekanje dok se izvodi veliki dio koda, to bi rezultiralo hrpom funkcija koje čekaju da budu pozvane, bez razdoblja odgode između njih da završe svoje izvršenje. Umjesto toga, preglednici imaju tendenciju čekati dok nema preostalo je više funkcija u redu čekanja prije dodavanja još jedne u red čekanja.

Dakle, možemo promatrati slučaj kada se treće aktiviranje povratnog poziva intervala poklapa s trenutkom kada je već izvršen. Ovo ilustrira važnu točku: intervalima nije važno što se trenutno izvodi, oni će biti dodani u red čekanja bez obzira na razdoblje odgode između izvršenja.

Konačno, nakon završetka drugog intervala povratnog poziva, vidjet ćemo da nema više ništa što bi JavaScript mehanizam mogao izvršiti. To znači da preglednik ponovno čeka na pojavu novih asinkronih događaja. To će se dogoditi na oznaci od 50 ms, gdje će ponovno raditi intervalni povratni poziv. U ovom trenutku neće biti ničega što bi ga blokiralo, pa će odmah raditi.

Pogledajmo primjer koji lijepo ilustrira razliku između setTimeout i setInterval.
setTimeout(function())( /* Neki dugi blok koda... */ setTimeout(arguments.callee, 10); ), 10); setInterval(function())( /* Neki dugi blok koda... */ ), 10);
Ove dvije opcije su na prvi pogled jednake, ali u stvarnosti nisu. Kod koji koristi setTimeout uvijek će imati odgodu od najmanje 10 ms nakon prethodnog poziva (može biti više, ali nikad manje), dok će kod koji koristi setInterval težiti pozivanju svakih 10 ms, bez obzira na to kada se prethodni poziv dogodio.

Rezimirajmo sve gore rečeno:
- JavaScript motori koriste okruženje s jednom niti, pretvarajući asinkrone događaje u red čekanja na izvršenje,
- Funkcije setTimeout i setInterval izvršavaju se bitno drugačije u asinkronom kodu,
- Ako se mjerač vremena ne može izvršiti u ovaj trenutak, odgodit će se do sljedeće točke izvršenja (koja će biti dulja od željene odgode),
- Intervali (setInterval) mogu se izvršavati jedan za drugim bez odgode ako njihovo izvršenje traje dulje od navedenog odgode.

Sve je ovo izuzetno važna informacija za razvoj. Poznavanje načina rada JavaScript mehanizma, posebno s puno asinkronih događaja (što se često događa), postavlja izvrsne temelje za izradu naprednih aplikacija.

Metoda setInterval(), ponuđena na sučeljima Window i Worker, više puta poziva funkciju ili izvršava isječak koda, s fiksnom vremenskom odgodom između svakog poziva. Vraća ID intervala koji jedinstveno identificira interval, tako da ga kasnije možete ukloniti pozivom clearInterval(). Ovu metodu definira mješavina WindowOrWorkerGlobalScope.

Sintaksa var intervalID = djelokrug.setInterval( funk, odgoditi, [arg1, arg2, ...]); var intervalID = djelokrug.setInterval( kodirati, odgoditi); Parametri func Funkcija koja se izvršava svake milisekunde odgode. Funkciji se ne prosljeđuju nikakvi argumenti i ne očekuje se povratna vrijednost. kod Neobavezna sintaksa omogućuje vam uključivanje niza umjesto funkcije, koja se kompilira i izvršava svake milisekunde kašnjenja. Ova sintaksa je ne preporučuje se iz istih razloga koji korištenje eval() čine sigurnosnim rizikom. kašnjenje Vrijeme, u milisekundama (tisućinke sekunde), koje mjerač vremena treba odgoditi između izvršavanja navedene funkcije ili koda. U nastavku pogledajte detalje o dopuštenom rasponu vrijednosti odgode. arg1, ..., argN Neobavezno Dodatni argumenti koji se prosljeđuju funkciji koju određuje funk kada mjerač vremena istekne.

Napomena: prosljeđivanje dodatnih argumenata u setInterval() u prvoj sintaksi ne funkcionira Internet Explorer 9 i ranije. Ako želite omogućiti ovu funkciju na tom pregledniku, morate koristiti polifill (pogledajte odjeljak).

Povratna vrijednost

Vraćeni intervalID je numerička vrijednost različita od nule koja identificira mjerač vremena kreiran pozivom na setInterval() ; ova se vrijednost može proslijediti za poništavanje vremenskog ograničenja.

Može biti korisno znati da setInterval() i setTimeout() dijele isti skup ID-ova i da se clearInterval() i clearTimeout() tehnički mogu koristiti naizmjenično. Međutim, radi jasnoće, pokušajte ih uvijek uskladiti kako biste izbjegli zabunu prilikom održavanja koda.

Napomena: Argument kašnjenja pretvara se u 32-bitni cijeli broj s predznakom. Ovo učinkovito ograničava kašnjenje na 2147483647 ms, budući da je navedeno kao cijeli broj s predznakom u IDL-u.

Primjeri Primjer 1: Osnovna sintaksa

Sljedeći primjer pokazuje osnovnu sintaksu funkcije setInterval().

Var intervalID = window.setInterval(myCallback, 500, "Parametar 1", "Parametar 2"); funkcija myCallback(a, b) ( // Vaš kod ovdje // Parametri su isključivo izborni. console.log(a); console.log(b); )

Primjer 2: Izmjena dviju boja

Sljedeći primjer poziva funkciju flashtext() jednom u sekundi dok se ne pritisne gumb Stop.

setInterval/clearInterval primjer var nIntervId; funkcija changeColor() ( nIntervId = setInterval(flashText, 1000); ) funkcija flashText() ( var oElem = document.getElementById("my_box"); oElem.style.color = oElem.style.color == "red" ? " blue" : "red"; // oElem.style.color == "red" ? "blue" : "red" je ternarni operator. ) funkcija stopTextColor() ( clearInterval(nIntervId); )

Pozdrav svijete

Stop

Primjer 3: Simulacija pisaćeg stroja

Sljedeći primjer simulira pisaći stroj prvo brisanjem, a zatim polaganim upisivanjem sadržaja u NodeList koji odgovara određenoj grupi selektora.

JavaScript Typewriter - MDN Primjer funkcije Typewriter (sSelector, nRate) ( function clean () ( clearInterval(nIntervId); bTyping = false; bStart = true; oCurrent = null; aSheets.length = nIdx = 0; ) funkcija pomicanja (oSheet, nPos , bEraseAndStop) (if (!oSheet.hasOwnProperty("dijelovi") || aMap.length< nPos) { return true; } var oRel, bExit = false; if (aMap.length === nPos) { aMap.push(0); } while (aMap < oSheet.parts.length) { oRel = oSheet.parts]; scroll(oRel, nPos + 1, bEraseAndStop) ? aMap++ : bExit = true; if (bEraseAndStop && (oRel.ref.nodeType - 1 | 1) === 3 && oRel.ref.nodeValue) { bExit = true; oCurrent = oRel.ref; sPart = oCurrent.nodeValue; oCurrent.nodeValue = ""; } oSheet.ref.appendChild(oRel.ref); if (bExit) { return false; } } aMap.length--; return true; } function typewrite () { if (sPart.length === 0 && scroll(aSheets, 0, true) && nIdx++ === aSheets.length - 1) { clean(); return; } oCurrent.nodeValue += sPart.charAt(0); sPart = sPart.slice(1); } function Sheet (oNode) { this.ref = oNode; if (!oNode.hasChildNodes()) { return; } this.parts = Array.prototype.slice.call(oNode.childNodes); for (var nChild = 0; nChild < this.parts.length; nChild++) { oNode.removeChild(this.parts); this.parts = new Sheet(this.parts); } } var nIntervId, oCurrent = null, bTyping = false, bStart = true, nIdx = 0, sPart = "", aSheets = , aMap = ; this.rate = nRate || 100; this.play = function () { if (bTyping) { return; } if (bStart) { var aItems = document.querySelectorAll(sSelector); if (aItems.length === 0) { return; } for (var nItem = 0; nItem < aItems.length; nItem++) { aSheets.push(new Sheet(aItems)); /* Uncomment the following line if you have previously hidden your elements via CSS: */ // aItems.style.visibility = "visible"; } bStart = false; } nIntervId = setInterval(typewrite, this.rate); bTyping = true; }; this.pause = function () { clearInterval(nIntervId); bTyping = false; }; this.terminate = function () { oCurrent.nodeValue += sPart; sPart = ""; for (nIdx; nIdx < aSheets.length; scroll(aSheets, 0, false)); clean(); }; } /* usage: */ var oTWExample1 = new Typewriter(/* elements: */ "#article, h1, #info, #copyleft", /* frame rate (optional): */ 15); /* default frame rate is 100: */ var oTWExample2 = new Typewriter("#controls"); /* you can also change the frame rate value modifying the "rate" property; for example: */ // oTWExample2.rate = 150; onload = function () { oTWExample1.play(); oTWExample2.play(); }; span.intLink, a, a:visited { cursor: pointer; color: #000000; text-decoration: underline; } #info { width: 180px; height: 150px; float: right; background-color: #eeeeff; padding: 4px; overflow: auto; font-size: 12px; margin: 4px; border-radius: 5px; /* visibility: hidden; */ }

CopyLeft 2012 Mozilla Developer Network

[ Igraj | Stanka | prekinuti]

Vivamus blandit massa ut metus mattis in fringilla lectus imperdiet. Proin ac ante a felis ornare vehicula. Fusce pellentesque lacus vitae eros convallis ut mollis magna pellentesque. Pellentesque placerat enim at lacus ultricies vitae facilisis nisi fringilla. U tincidunt tincidunt tincidunt. JavaScript pisaći stroj

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ultrices dolor ac dolor imperdiet ullamcorper. Suspendisse quam libero, luctus auctor mollis sed, malesuada condimentum magna. Quisque in ante tellus, in placerat est. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec a mi magna, quis mattis dolor. Etiam sit amet ligula quis urna auctor imperdiet nec faucibus ante. Mauris vel consectetur dolor. Nunc eget elit eget velit pulvinar fringilla consectetur 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, suscipit a hendrerit vitae, volutpat non ipsum.

Phasellus ac nisl lorem:
Nullam commodo suscipit lacus non aliquet. Phasellus ac nisl lorem, sed facilisis ligula. Nam cursus lobortis placerat. Sed dui nisi, elementum eu sodales ac, placerat sit amet mauris. Pellentesque dapibus tellus ut ipsum aliquam eu auctor dui vehicula. Quisque ultrices laoreet erat, at ultrices tortor sodales non. Sed venenatis luctus magna, ultricies ultricies nunc fringilla eget. Praesent scelerisque urna vitae nibh tristique varius consequat neque luctus. Integer ornare, erat a porta tempus, velit justo fermentum elit, a fermentum metus nisi eu ipsum. Vivamus eget augue vel dui viverra adipiscing congue ut massa. Praesent vitae eros erat, pulvinar laoreet magna. Mecenas vestibulum mollis nunc in posuere. Pellentesque sit amet metus a turpis lobortis tempor eu vel tortor. Cras sodales eleifend interdum.

Duis lobortis sapien quis nisl luctus porttitor. In tempor semper libero, eu tincidunt dolor eleifend sit amet. Ut nec velit in dolor tincidunt rhoncus non non diam. Morbi auctor ornare orci, non euismod felis gravida nec. Curabitur elementum nisi a eros rutrum nec blandit diam placerat. Aenean tincidunt risus ut nisi consectetur cursus. Ut vitae quam elit. Donec dignissim est in quam tempor consequat. Aliquam aliquam diam non felis convallis suscipit. Nulla facilisi. Donec lacus risus, dignissim et fringilla et, egestas vel eros. Duis malesuada accumsan dui, at fringilla mauris bibStartum quis. 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, consectetur adipiscing elit. Sed nec libero nunc. Nullam tortor nunc, elementum a consectetur et, ultrices eu orci. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a nisl eu sem vehicula egestas.

Argumenti povratnog poziva

Kao što je prethodno objašnjeno, Internet Explorer verzije 9 i niže ne podržavaju prosljeđivanje argumenata funkciji povratnog poziva ni u setTimeout() ni u setInterval(). Sljedeći kôd specifičan za IE pokazuje metodu za prevladavanje ovog ograničenja. Za korištenje jednostavno dodajte sljedeći kod na vrh svoje skripte.

/*\ |*| |*| Polifil specifičan za IE koji omogućuje prolaz proizvoljnih argumenata u |*| funkcije povratnog poziva javascript mjerača vremena (standardna sintaksa HTML5)..setInterval |*| https://site/Korisnik:fusionchess |*| |*| Sintaksa: |*| var timeoutID = window.setTimeout(func, delay[, arg1, arg2, ...]); |*| var timeoutID = window.setTimeout(code, delay); |*| var intervalID = window.setInterval(func, delay[, arg1, arg2, ...]); |*| var intervalID = window.setInterval(code, delay); |*| \*/ if (document.all && !window.setTimeout.isPolyfill) ( var __nativeST__ = window.setTimeout; window.setTimeout = funkcija (vCallback, nDelay /*, argumentToPass1, argumentToPass2, itd. */) ( var aArgs = Array .prototype.slice.call(arguments, 2); return __nativeST__(vCallback instanceof Function () ( vCallback.apply(null, aArgs); ) : vCallback, nDelay ); if (document.all && !window.setInterval.isPolyfill) ( var __nativeSI__ = window.setInterval; window.setInterval = funkcija (vCallback, nDelay /*, argumentToPass1, argumentToPass2, itd. */) ( var aArgs = Array.prototype. slice.call(arguments, 2); return __nativeSI__(vCallback instanceof funkcija () (vCallback.apply(null, aArgs); ) : vCallback, nDelay);

Druga mogućnost je korištenje anonimne funkcije za pozivanje povratnog poziva, iako je ovo rješenje malo skuplje. Primjer:

Var intervalID = setInterval(function() ( myFunc("jedan", "dva", "tri"); ), 1000); var intervalID = setInterval(funkcija(arg1) ().bind(undefined, 10), 1000);

Neaktivne kartice Zahtijeva Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)

Počevši od Gecka 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2), intervali su ograničeni da se ne aktiviraju češće od jednom u sekundi u neaktivnim karticama.

Problem "ovaj".

Kada metodu proslijedite setInterval() ili bilo kojoj drugoj funkciji, ona se poziva s pogrešnom this vrijednošću. Ovaj problem je detaljno objašnjen u JavaScript referenci.

Obrazloženje

Kod koji izvodi setInterval() izvodi se u zasebnom kontekstu izvršavanja od funkcije iz koje je pozvan. Kao posljedica toga, ključna riječ this za pozvanu funkciju postavljena je na objekt window (ili globalni), nije ista kao vrijednost this za funkciju koja je pozvala setTimeout. Pogledajte sljedeći primjer (koji koristi setTimeout() umjesto setInterval() – problem je, zapravo, isti za oba mjerača vremena):

MyArray = ["nula", "jedan", "dva"]; myArray.myMethod = funkcija (sProperty) ( alert(arguments.length > 0 ? this : this); ); moj niz.moja metoda(); // ispisuje "nula, jedan, dva" myArray.myMethod(1); // ispisuje "jedan" setTimeout(myArray.myMethod, 1000); // ispisuje "" nakon 1 sekunde setTimeout(myArray.myMethod, 1500, "1"); // ispisuje "undefined" nakon 1,5 sekunde // prosljeđivanje objekta "this" s .call neće raditi // jer će ovo promijeniti vrijednost ovog unutar samog setTimeouta // dok mi želimo promijeniti vrijednost ovog unutar myArray .myMethod // zapravo će biti pogreška jer kod setTimeout očekuje da ovo bude objekt prozora: setTimeout.call(myArray.myMethod, 2000); // pogreška: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Ilegalna operacija na objektu prototipa WrappedNative" setTimeout.call(myArray, myArray.myMethod, 2500, 2); // ista pogreška

Kao što vidite, nema načina za prosljeđivanje ovog objekta funkciji povratnog poziva u naslijeđenom JavaScriptu.

Moguće rješenje

Mogući način rješavanja problema "ovaj" je zamjena dviju izvornih globalnih funkcija setTimeout() ili setInterval() s dvije nedomaćinski one koje omogućuju njihovo pozivanje putem metode Function.prototype.call. Sljedeći primjer pokazuje moguću zamjenu:

// Omogući prolaz "ovog" objekta kroz JavaScript timere var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval; window.setTimeout = funkcija (vCallback, nDelay /*, argumentToPass1, argumentToPass2, itd. */) ( var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2); return __nativeST__(vCallback instanceof Function ? function () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay); window.setInterval = funkcija (vCallback, nDelay /*, argumentToPass1, argumentToPass2, itd. */) ( var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2); return __nativeSI__(vCallback instanceof Function ? function () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay);

Ove dvije zamjene također omogućuju HTML5 standardni prijenos proizvoljnih argumenata u funkcije povratnog poziva mjerača vremena u IE. Tako da se mogu koristiti kao nestandardno usklađen polifili također. Pogledajte za a u skladu sa standardima polifil.

Test novih značajki:

MyArray = ["nula", "jedan", "dva"]; myArray.myMethod = funkcija (sProperty) ( alert(arguments.length > 0 ? this : this); ); setTimeout(upozorenje, 1500, "Zdravo svijete!"); // standardna upotreba setTimeout i setInterval je sačuvana, ali... setTimeout.call(myArray, myArray.myMethod, 2000); // ispisuje "nula, jedan, dva" nakon 2 sekunde setTimeout.call(myArray, myArray.myMethod, 2500, 2); // ispisuje "dva" nakon 2,5 sekunde

Za složeniju, ali još uvijek modularnu verziju ( Demon) pogledajte Upravljanje JavaScript demonima . Ova složenija verzija nije ništa drugo nego velika i skalabilna zbirka metoda za Demon konstruktor. Međutim Demon sam konstruktor nije ništa drugo nego klon MiniDaemon s dodatnom podrškom za u tome i na početku funkcije deklarirane tijekom instanciranja demon. Dakle, MiniDaemon framework ostaje preporučeni način za jednostavne animacije jer Demon bez svoje zbirke metoda u biti je njegov klon.

minidaemon.js /*\ |*| |*| :: MiniDaemon:: |*| |*| Revizija #2 - 26. rujna 2014. setInterval |*| https://site/Korisnik:fusionchess |*| https://github.com/madmurphy/minidaemon.js |*| |*| Ovaj okvir je objavljen pod GNU Lesser General Public License, verzija 3 ili novija. |*| http://www.gnu.org/licenses/lgpl-3.0.html |*| \*/ funkcija MiniDaemon (oOwner, fTask, nRate, nLen) ( if (!(ova && ova instanca MiniDaemona)) ( return; ) if (arguments.length< 2) { throw new TypeError("MiniDaemon - nedovoljno argumenti"); ) if (oVlasnik) ( 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.rate = 100; / MiniDaemon.prototype.INDEX = 0; MiniDaemon.prototype.BACKW = true; .forceCall = function (oDmn.INDEX += oDmn.BACKW) ? -1: 1; if (oDmn.owner, oDmn.INDEX, oDmn.length, oDmn.BACKW) === false || oDmn.isAtEnd()) ( oDmn.pause(); return false; ) return true ); /* Metode instanci */ MiniDaemon.prototype.isAtEnd = function () ( return this.BACKW ? isFinite(this.length) && this.INDEX< 1: this.INDEX + 1 >ovo.duljina; ); MiniDaemon.prototype.synchronize = function () ( if (this.PAUSED) ( return; ) clearInterval(this.SESSION); this.SESSION = setInterval(MiniDaemon.forceCall, this.rate, this); ); MiniDaemon.prototype.pause = function () ( clearInterval(this.SESSION); this.PAUSED = true; ); MiniDaemon.prototype.start = funkcija (bReverse) ( var bBackw = Boolean(bReverse); if (this.BACKW === bBackw && (this.isAtEnd() || !this.PAUSED)) ( return; ) this.BACKW = bBackw; this.PAUSED = false; this.synchronize();

MiniDaemon prosljeđuje argumente funkciji povratnog poziva. Ako želite raditi na tome s preglednicima koji izvorno ne podržavaju ovu značajku, koristite jednu od gore predloženih metoda.

Sintaksa

var myDaemon = novi MiniDaemon( thisObject, uzvratiti poziv[ , stopa [, duljina]]);

Opis Napomene o korištenju

Funkcija setInterval() obično se koristi za postavljanje odgode za funkcije koje se uvijek iznova izvršavaju, kao što su animacije. Interval možete poništiti pomoću WindowOrWorkerGlobalScope.clearInterval() .

Ako želite da se vaša funkcija pozove jednom nakon navedene odgode, koristite .

Ograničenja kašnjenja

Moguće je da intervali budu ugniježđeni; to jest, povratni poziv za setInterval() može zauzvrat pozvati setInterval() da započne izvođenje drugog intervala, iako prvi još traje. Da bi se ublažio potencijalni utjecaj koji to može imati na performanse, nakon što su intervali ugniježđeni dublje od pet razina, preglednik će automatski nametnuti minimalnu vrijednost od 4 ms za interval. Pokušaji navođenja vrijednosti manje od 4 ms u duboko ugniježđenim pozivima za setInterval() bit će prikvačeni na 4 ms.

Preglednici mogu nametnuti čak i strože minimalne vrijednosti za interval pod nekim okolnostima, iako to ne bi trebalo biti uobičajeno. Također imajte na umu da stvarna količina vremena koja protekne između poziva za povratni poziv može biti dulja od dane odgode; pogledajte Razlozi za kašnjenja dulja od navedenih u WindowOrWorkerGlobalScope.setTimeout() za primjere.

Osigurajte da je trajanje izvršenja kraće od učestalosti intervala

Ako postoji mogućnost da bi vašoj logici trebalo dulje da se izvrši od vremena intervala, preporučuje se da rekurzivno pozovete imenovanu funkciju koristeći setTimeout() . Na primjer, ako koristite setInterval() za ispitivanje udaljenog poslužitelja svakih 5 sekundi, latencija mreže, poslužitelj koji ne reagira i niz drugih problema mogli bi spriječiti dovršetak zahtjeva u dodijeljenom vremenu. Kao takvi, mogli biste se naći s XHR zahtjevima u redu čekanja koji se neće nužno vratiti po redu.

U programiranju skriptni jezici S vremena na vrijeme potrebno je napraviti pauzu - nakratko zaustaviti izvođenje programa, a zatim nastaviti s radom. Na primjer, u VBS i PHP skriptama moguće su sljedeće metode:

VBS: wscript.sleep 1500 (zaustavi se na 1,5 sekundi)

PHP: spavanje(10); (zaustavite 10 sekundi)

Tijekom takvih pauza, runtime sustav (PHP ili VBS) ne radeći ništa. Programer koji pokuša intuitivno koristiti nešto slično u Javascriptu bit će neugodno iznenađen. Uobičajena greška kada pokušavate stvoriti pauzu u Javascriptu, to izgleda ovako:

Funkcija badtest() ( for (var i=1; i< 10; i++) { window.setTimeout("document.getElementById("test1").value += " + i, 900) } }

Mislite da kada tijekom petlje dođe red na izvlačenje sljedećeg broja, vaš setTimeout će pošteno zaustaviti Javascript u radu, pričekajte 0,9 sekundi, dodajte željeni broj na kraj polja za unos i onda nastavite s radom. Ali u stvarnosti to nije točno: setInterval i setTimeout u Javascriptu samo odgađaju izvršenje radnje (ili funkcije) navedene u zagradama. U našem primjeru dogodit će se sljedeće:

  • i = 1;
  • odgoditi dodavanje broja "1" u polje za unos za 0,9 sekundi;
  • Odmah nakon postavljanja ovog problema, ciklus se nastavlja: i=2;
  • odgoditi dodavanje broja "2" u polje za unos za 0,9 sekundi;
  • Odmah znači, na primjer, 1 ms (to jest, neproporcionalno malo u usporedbi s 900 ms): petlja će obaviti svoj posao gotovo trenutno, stvarajući nekoliko odgođenih zadataka iz iste vremenske točke. To znači da će svi zadaci "crtanja" na čekanju biti završeni gotovo u isto vrijeme, bez pauza između dodavanja novih brojeva. Ciklus počinje; sve se zamrzava 0,9 s; i shirr - svi brojevi se nižu jedan za drugim.

    Kako pravilno primijeniti setTimeout u takvom slučaju? Komplicirano je. Morat ćete pozvati funkciju rekurzivno(iznutar funkcije ista funkcija), a kako ovaj proces ne bi bio beskrajan, postavite uvjet zaustavljanja (npr. veličinu broja koji se ispisuje):

    Funkcija welltest() ( if (tj< 9) { document.getElementById("test2").value += ++i window.setTimeout("welltest()", 400) } }

    A varijabla i morat će se inicijalizirati izvan funkcije - na primjer, ovako:

    Sada sve radi kako treba (smanjili smo vrijeme kašnjenja s 0,9 s na 0,4 s). Ali za takve zadatke logičnije je koristiti setInterval umjesto setTimeout (iako će to zahtijevati dvije funkcije):

    Funkcija besttest() ( window.i = 0 window.timer1 = window.setInterval("draw()", 400) ) funkcija draw() (document.getElementById("test3").value += ++i if (i >= 9) clearInterval(window.timer1) )

    Osobitost metode Javascirpt setInterval je u tome što ne prolazi "sama od sebe"; mora se zaustaviti posebnom metodom clearInterval. A kako bi bilo jasno što točno zaustaviti, zadatku za odgođenu radnju dodjeljuje se poseban identifikator - mjerač vremena: window.timer1 = window.setInterval(...) .

    Identifikatori se također mogu dodijeliti zadacima kreiranim metodom setTimeout. Svi ID-ovi mjerača vremena moraju se međusobno razlikovati (jedinstveni unutar trenutnog prozora preglednika). Tada možete stvoriti nekoliko različitih zadataka u prozoru koji koriste odgođene radnje, a ti će se zadaci izvršavati paralelno (nekako istovremeno, ako računalo ima dovoljno resursa), što je u osnovi nemoguće u PHP-u ili VBS-u.

    Evo primjera stranice s nekoliko Javascript timera koji rade istovremeno: setinterval.htm(Javascript funkcionira u datoteci setinterval.js). Svi mjerači vremena stranica (osim izbornika) mogu se zaustaviti tipkom Esc. Svi primjeri mjerača vremena temelje se na "prirodnom" (a ne apstraktnom i++) odbrojavanju - vremenu ili udaljenosti. Svi "satovi" su posebno desinkronizirani (radi jasnoće). Tajmeri ovisni o udaljenosti koriste se u "indikatoru" iu padajućem ("izvlačnom") izborniku.

    Padajući izbornik

    Naš klizni izbornik zapravo je klizni (ispod "zaglavlja"): između elemenata su posebno ostavljeni razmaci tako da možete vidjeti kako klizi van. Neočekivano se pokazalo da ne možemo napraviti jednako gladak izlaz za popise različitih duljina - vjerojatno zbog niske performanse računala ( AMD Athlon 999 MHz).

    Sasvim je očito da je za ljepotu i sklad potrebno da se popisi različitih stavki jelovnika pojavljuju u isto vrijeme. Odnosno, dulji popisi trebali bi ispasti s više velika brzina, kraće - manjom brzinom. Čini se da bi se to moglo implementirati ovako:

  • Postavljamo ukupno vrijeme "odlaska", na primjer, 200 ms.
  • Ako padajući popis ima visinu od 20 px, očito je da ga možemo pomaknuti jedan piksel prema dolje u intervalu od 10 ms - i tada će za 200 ms izaći cijeli popis.
  • Ako je padajući izbornik visok 40 piksela, da bismo stali u isto vrijeme, moramo ga pomaknuti za jedan piksel prema dolje svakih 5 ms.
  • Po ovoj logici, ako je padajući popis visok 200 piksela, trebali bismo ga pomaknuti za jedan piksel prema dolje svakih 1 ms. Ali takva brzina ne radi na našem računalu - preglednik jednostavno nema vremena iscrtati novu poziciju popisa u jednoj milisekundi. Da. Javascript uspijeva brojati (što se ima brojati?), ali preglednik (Firefox) nema vremena za prikaz. Tipična situacija za web.

    Dakle, koliko-toliko je moguće ujednačiti vrijeme odlaska izbornika samo uz pomoć štaka, a još je nejasno kako će to funkcionirati za više brzo računalo. Ali treba računati na najsporijeg, zar ne? Algoritam (bez uzimanja u obzir brzine računala) ispada ovako:

  • Postavite ukupno vrijeme za odjavu popisa: vrijeme = 224 (ms).
  • Postavljamo minimalno vrijeme za jedan interval u ciklusu: kašnjenje = 3 (ms).
  • Postavite minimalni korak za pomicanje liste: pomak = 1 (px).
  • Sve to mijenjamo ovisno o visini liste: 1) povećavamo vrijeme kašnjenja (intervala) obrnuto proporcionalno visini i izravno proporcionalno ukupnom vremenskom vremenu (na visini 224 koeficijent je 1); 2) ako je visina veća od 40 px, povećajte minimalni korak proporcionalno visini. Konstanta "40" dobivena je eksperimentalno za najsporije računalo. Testovi na računalu s procesorom Pentium 4 2,53 GHz otkrili su točno isti broj - 40. U suprotnom, mjerači vremena ne rade ispravno, popisi se poremete.
  • Sada manje-više izlaze liste. Za više-manje slično vrijeme. Na stranici setinterval.htm.

    I dolazi Bruce:

    Funkcija slide_do(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 } } }

    Sama funkcija koja izbacuje ugniježđene liste iz izbornika je, kao što vidimo, vrlo jednostavna. Sve što preostaje je pokrenuti ga s nečim poput ovog retka:

    Ts.timer1 = setInterval(function())(slide_do(ts, maxtop, offset)), kašnjenje)

    Pa, prije nego što počnete, samo izračunajte sve te maxtop i offset, a također postavite listu na mintop poziciju. To radi "preliminarna" funkcija slide() od 40 redaka. I sve zajedno - u datoteku setinterval.js. Da, i ovo sranje uopće neće raditi bez uključene datoteke stilova



    reci prijateljima
    Pročitajte također