Ponovite radnje u određenom javascript vremenskom intervalu. Primjeri jQuery funkcije setTimeout()

Dom / Tehnologije

Metoda setInterval(), ponuđena na sučeljima Window i Worker, više puta poziva funkciju ili izvršava isječak koda, sa fiksnim vremenskim kašnjenjem između svakog poziva.

Vraća ID intervala koji jedinstveno identificira interval, tako da ga možete ukloniti kasnije pozivanjem clearInterval() . Ovu metodu definira miksin WindowOrWorkerGlobalScope. Sintaksa = var intervalID obim .setInterval(, func, [kašnjenje, arg1, ...]); Sintaksa = var intervalID obim arg2, func kod ); Parameters func Funkcija koja se izvršava svakih milisekundi kašnjenja. Funkcijama se ne prosljeđuju argumenti i ne očekuje se povratna vrijednost. code Opciona sintaksa vam omogućava da uključite string umesto funkcije, koja se kompajlira i izvršava svakih milisekundi kašnjenja. Ova sintaksa je .setInterval( ne preporučuje se

iz istih razloga zbog kojih korištenje eval() predstavlja sigurnosni rizik. kašnjenje Vrijeme, u milisekundama (hiljaditim dijelovima sekunde), tajmer bi trebao kasniti između izvršavanja navedene funkcije ili koda. Pogledajte ispod za detalje o dozvoljenom rasponu vrijednosti kašnjenja. arg1, ..., argN Opcijski Dodatni argumenti koji se prosljeđuju funkciji koju specificira

kada tajmer istekne.

Napomena: Prosljeđivanje dodatnih argumenata u setInterval() u prvoj sintaksi ne funkcionira

Internet Explorer

9 i ranije. Ako želite da omogućite ovu funkciju na tom pretraživaču, morate koristiti polifil (pogledajte odjeljak).

Povratna vrijednost

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

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

Primjer 2: Izmjenjivanje dvije boje

Sljedeći primjer poziva funkciju flashtext() jednom u sekundi dok se ne pritisne dugme 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 == "crveno" ? " blue" : "red"; // oElem.style.color == "red" ? "blue" : "red" je ternarni operator. ) funkcija stopTextColor() ( clearInterval(nIntervId); )

Hello World

Stani

Primjer 3: Simulacija pisaće mašine

Sljedeći primjer simulira pisaću mašinu tako što prvo brišete, a zatim polako upisujete sadržaj u NodeList koji odgovara određenoj grupi selektora.< 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; */ }

JavaScript pisaća mašina - MDN Primjer funkcije Pisaća mašina (sSelector, nRate) ( funkcija clean () ( clearInterval(nIntervId); bTyping = false; bStart = true; oCurrent = null; aSheets.length = nIdx = 0; ) funkcija skrolovanja (oSheet, nPos , bEraseAndStop) ( if (!oSheet.hasOwnProperty("parts") || aMap.length

CopyLeft 2012 od Mozilla Developer Network

[ Igraj | Pauza | 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. In tincidunt tincidunt tincidunt.

JavaScript pisaća mašina
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. Maecenas 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 sempre 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 u setTimeout() ili setInterval() . Sljedeći kod specifičan za IE pokazuje metodu za prevazilaženje ovog ograničenja. Za korištenje, jednostavno dodajte sljedeći kod na vrh vaše skripte.

/*\ |*| |*| Polifill specifično za IE koji omogućava prolaz proizvoljnih argumenata u |*| callback funkcije javascript tajmera (HTML5 standardna sintaksa)..setInterval |*| https://site/User:fusionchess |*| |*| Sintaksa: |*| var timeoutID = window.setTimeout(func, kašnjenje[, arg1, arg2, ...]); |*| var timeoutID = window.setTimeout(code, kašnjenje); |*| var intervalID = window.setInterval(func, kašnjenje[, arg1, arg2, ...]); |*| var intervalID = window.setInterval(code, kašnjenje); |*| \*/ 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); ( var __nativeSI__ = window.setInterval; window.setInterval = funkcija (vCallback, nDelay /*, argumentToPass1, argumentToPass2, itd. */) ( var aArgs = Array.prototype. slice.call(arguments, 2); return __nativeSI__(vCall instanceof Function () ( 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(function(arg1) ().bind(undefined, 10), 1000);

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

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

"Ovaj" problem

Kada prosledite metodu setInterval() ili bilo kojoj drugoj funkciji, ona se poziva sa pogrešnom ovom vrednošću. Ovaj problem je detaljno objašnjen u JavaScript referenci.

Objašnjenje

MyArray = ["nula", "jedan", "dva"]; myArray.myMethod = funkcija (sProperty) ( alert(arguments.length > 0 ? ovo : ovo); ); myArray.myMethod(); // 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 sekundi // prosljeđivanje "this" objekta sa .call neće raditi // jer će ovo promijeniti vrijednost ovog unutar samog setTimeout-a // dok mi želimo promijeniti vrijednost ovog unutar myArray .myMethod // u stvari, to će biti greška jer setTimeout kod očekuje da će ovo biti objekt prozora: setTimeout.call(myArray, myArray.myMethod, 2000 // greška: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Nedozvoljena operacija na WrappedNative prototip objektu"); setTimeout.call(myArray, myArray.myMethod, 2500, 2) // ista greška

Kao što vidite, ne postoje načini da se ovaj objekat proslijedi funkciji povratnog poziva u naslijeđenom JavaScriptu.

Moguće rješenje

Mogući način da se riješi "ovaj" problem je zamjena dvije izvorne globalne funkcije setTimeout() ili setInterval() sa dvije ne-domaći one koje omogućavaju njihovo pozivanje putem Function.prototype.call metode. Sljedeći primjer pokazuje moguću zamjenu:

// Omogućava prolazak "this" objekta kroz JavaScript tajmere 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? funkcija? () ( 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 ? funkcija? () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay);

Ove dvije zamjene također omogućavaju standardni HTML5 prolaz proizvoljnih argumenata funkcijama povratnog poziva tajmera u IE. Tako da se mogu koristiti kao nestandardno usklađen polifile takođe. Pogledajte za a u skladu sa standardima polyfill

Test nove funkcije:

MyArray = ["nula", "jedan", "dva"]; myArray.myMethod = funkcija (sProperty) ( alert(arguments.length > 0 ? ovo : ovo); ); setTimeout(alert, 1500, "Zdravo svijete!"); // standardna upotreba setTimeout i setInterval je oč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 ( Daemon) vidi upravljanje JavaScript demonima. Ova složenija verzija nije ništa drugo do velika i skalabilna zbirka metoda za Daemon konstruktor. Međutim, the Daemon sam konstruktor nije ništa drugo nego klon MiniDaemon sa dodatnom podrškom za init i onstart funkcije deklarirane tokom instanciranja daemon. Dakle MiniDaemon framework ostaje preporučeni način za jednostavne animacije, jer Daemon bez svoje zbirke metoda je u suštini njegov klon.

minidaemon.js /*\ |*| |*| :: MiniDaemon:: |*| |*| Revizija #2 - 26. septembar 2014.setInterval |*| https://site/User:fusionchess |*| https://github.com/madmurphy/minidaemon.js |*| |*| Ovaj okvir je objavljen pod GNU-ovom manjom općom javnom licencom, verzija 3 ili novija. |*| http://www.gnu.org/licenses/lgpl-3.0.html |*| \*/ funkcija MiniDaemon (vlasnik, fTask, nRate, nLen) ( if (!(ova && ova instanca MiniDaemon)) ( return; ) 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 = null; MiniDaemon.prototype.rate = 100; MiniDaemon.prototype.length = Beskonačnost;< 1: this.INDEX + 1 >this.length; ); MiniDaemon.prototype.synchronize = funkcija () ( 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;

MiniDaemon prosljeđuje argumente funkciji povratnog poziva. Ako želite da radite na tome sa pretraživačima koji izvorno ne podržavaju ovu funkciju, koristite jednu od gore predloženih metoda.

Sintaksa

var myDaemon = novi MiniDaemon( thisObject, povratni poziv[ , stopa [, dužina]]);

Opis Napomene o upotrebi

Funkcija setInterval() se obično koristi za postavljanje kašnjenja za funkcije koje se izvršavaju iznova i iznova, kao što su animacije. Interval možete otkazati koristeći WindowOrWorkerGlobalScope.clearInterval() .

Ako želite da se vaša funkcija zove jednom nakon navedenog kašnjenja, koristite .

Ograničenja odlaganja

Moguće je da intervali budu ugniježđeni; to jest, povratni poziv za setInterval() može zauzvrat pozvati setInterval() da pokrene drugi interval koji se izvodi, iako prvi još uvijek traje. Da bi se ublažio potencijalni utjecaj koji ovo može imati na performanse, kada su intervali ugniježđeni iznad pet nivoa, pretraživač će automatski primijeniti minimalnu vrijednost od 4 ms za interval. Pokušaji da se navede vrijednost manja od 4 ms u duboko ugniježđenim pozivima setInterval() će biti zakačeni na 4 ms.

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

Osigurajte da je trajanje izvršavanja kraće od frekvencije intervala

Ako postoji mogućnost da bi vaša logika mogla da potraje duže od vremena intervala, preporučuje se da rekurzivno pozovete imenovanu funkciju koristeći setTimeout() . Na primjer, ako koristite setInterval() za anketiranje udaljenog servera svakih 5 sekundi, kašnjenje mreže, server koji ne reaguje i mnoštvo drugih problema mogu spriječiti završetak zahtjeva u dodijeljenom vremenu. Kao takvi, možete se naći sa XHR zahtjevima u redu koji se neće nužno vratiti u red.

U programiranju u skript jezicima, periodično postoji potreba da se napravi pauza - da se na neko vreme pauzira izvršavanje programa, a zatim nastavi sa radom. Na primjer, u VBS i PHP skriptama moguće su sljedeće metode:

VBS: wscript.sleep 1500 (zaustavljanje na 1,5 sekunde)

PHP: sleep(10); (zaustavite se 10 sekundi)

Tokom takvih pauza, sistem za izvršavanje (PHP ili VBS) ne radi ništa. Programer koji pokušava intuitivno da koristi nešto slično u Javascriptu biće neprijatno iznenađen. Uobičajena greška kada pokušavate napraviti pauzu u Javascript-u to izgleda ovako:

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

Mislite da kada tokom petlje dođe red na izvlačenje sledećeg broja, vaš setTimeout će iskreno zaustaviti Javascript rad, sačekati 0,9 sekundi, dodati željeni broj na kraj polja za unos i onda nastaviti sa radom. Ali u stvarnosti to nije tačno: setInterval i setTimeout u Javascriptu samo odlažu izvršenje akcije (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, nesrazmjerno malo u odnosu na 900 ms): petlja će svoj posao obaviti gotovo trenutno, stvarajući nekoliko odgođenih zadataka iz istog trenutka. 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 zamrzne na 0,9 s; i shirr - svi brojevi se pucaju jedan za drugim.

    Kako pravilno primijeniti setTimeout u takvom slučaju? Komplikovano je. Morat ćete pozvati funkciju rekurzivno(unutar funkcije ista funkcija), i da ovaj proces ne bude beskonačan, postavite uslov zaustavljanja (na primjer, veličinu broja koji se ispisuje):

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

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

    Sada sve radi kako treba (smanjili smo vrijeme kašnjenja sa 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) )

    Posebnost metode Javascirpt setInterval je u tome što ona ne prolazi “sama po sebi” mora biti zaustavljena posebnom metodom clearInterval; I da bi bilo jasno šta tačno zaustaviti, zadatku za odloženu akciju se dodeljuje poseban identifikator - tajmer: window.timer1 = window.setInterval(...) .

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

    Evo primjera stranice sa nekoliko Javascript tajmera koji rade istovremeno: setinterval.htm (Javascript funkcije u datoteci setinterval.js). Svi tajmeri stranica (osim menija) mogu se zaustaviti pomoću tipke Esc. Svi primjeri tajmera zasnovani su na “prirodnom” (a ne apstraktnom i++) odbrojavanju - vremenu ili udaljenosti. Svi "satovi" su posebno desinhronizovani (radi jasnoće). Tajmeri ovisni o udaljenosti koriste se u “indikatoru” iu padajućem (“izvlačeći”) izborniku.

    Padajući meni

    Naš klizni meni je zapravo klizni (ispod „zaglavlja“): praznine su posebno ostavljene između elemenata tako da možete vidjeti kako izmiče. Neočekivano, ispostavilo se da nismo mogli da učinimo izlaz jednako glatkim za liste različitih dužina – verovatno zbog niskih performansi računara (AMD Athlon 999 MHz).

    Sasvim je očigledno da je za ljepotu i sklad neophodno da se liste različitih stavki na meniju pojavljuju istovremeno. To jest, duže liste bi trebale ispasti sa više velike brzine, kraće - pri manjoj brzini. Čini se da bi se ovo moglo implementirati na sljedeći način:

  • Ukupno vrijeme "odlaska" postavljamo, na primjer, na 200 ms.
  • Ako padajuća lista ima visinu od 20 px, očigledno je da je možemo pomeriti za jedan piksel naniže u intervalu od 10 ms - i onda će za 200 ms cela lista izaći.
  • Ako je padajući meni visok 40px, da bi se uklopio u isto vreme, moramo ga pomeriti za jedan piksel nadole svakih 5ms.
  • Po ovoj logici, ako je padajuća lista visoka 200px, trebali bismo je pomjeriti za jedan piksel na svakih 1ms. Ali takva brzina ne radi na našem računaru - pretraživač jednostavno nema vremena da nacrta novu poziciju liste u jednoj milisekundi. Da. Javascript uspeva da broji (šta ima da se broji?), ali pretraživač (Firefox) nema vremena za prikaz. Tipična situacija za web.

    Stoga je moguće manje-više izjednačiti vrijeme polaska iz menija samo uz pomoć štaka, a još uvijek je nejasno kako će to funkcionirati za više brz kompjuter. Ali treba računati na najsporijeg, zar ne? Algoritam (bez uzimanja u obzir brzine računara) ispada otprilike ovako:

  • Postavite ukupno vrijeme za provjeru liste: vrijeme = 224 (ms).
  • Postavljamo minimalno vrijeme za jedan interval u ciklusu: kašnjenje = 3 (ms).
  • Postavite minimalni korak za pomeranje liste: ofset = 1 (px).
  • Sve ovo menjamo u zavisnosti od visine liste: 1) povećavamo vreme kašnjenja (interval) obrnuto proporcionalno visini i direktno proporcionalno ukupnom vremenu (na visini od 224 koeficijent je 1); 2) ako je visina veća od 40 px, povećajte minimalni korak proporcionalno visini. Konstanta "40" dobijena je eksperimentalno za najsporiji računar. Testovi na Pentium 4 CPU 2.53GHz računaru su otkrili potpuno isti broj - 40. U suprotnom, tajmeri pokvare svoj rad, liste nestaju.
  • Sada više-manje izlaze liste. Za manje-više 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 gura ugniježđene liste iz menija je, kao što vidimo, vrlo jednostavna. Sve što ostaje je da ga pokrenete sa nečim poput ove linije:

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

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

    Izuzetno je važno razumjeti kako rade JavaScript tajmeri. Često se njihovo ponašanje ne poklapa s našim intuitivnim razumijevanjem višenitnog rada, a to je zbog činjenice da se u stvarnosti izvršavaju u jednoj niti. Pogledajmo četiri funkcije pomoću kojih možemo upravljati tajmerima:

    • var id = setTimeout(fn, kašnjenje); - Kreira jednostavan tajmer koji će pozvati datu funkciju nakon određenog kašnjenja. Funkcija vraća jedinstveni ID s kojim se tajmer može pauzirati.
    • var id = setInterval(fn, kašnjenje); - Slično kao setTimeout, ali kontinuirano poziva funkciju u određenom intervalu (sve dok se ne zaustavi).
    • clearInterval(id);, clearTimeout(id); - Prihvata ID tajmera (koji se vraća jednom od gore opisanih funkcija) i zaustavlja izvršenje povratnog poziva"a.
    Glavna ideja koju treba uzeti u obzir je da tačnost perioda kašnjenja tajmera nije zagarantovana. Za početak, pretraživač izvršava sve asinhrone JavaScript događaje u jednoj niti (kao što su klikovi mišem ili tajmeri) i to samo u vrijeme kada je na redu taj događaj. To najbolje pokazuje sljedeći dijagram:

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

    JavaScript može izvršiti samo jedan dio koda (zbog jednonitne prirode izvršenja), od kojih svaki blokira izvršavanje drugih asinhronih događaja. To znači da kada se desi asinhroni događaj (kao što je klik mišem, poziv tajmera ili završetak XMLHttp zahtjeva), on se dodaje u red i izvršava kasnije (naravno, implementacija varira u zavisnosti od pretraživača, ali hajde da se složimo da nazovite to "red").

    Za početak, zamislimo da dva tajmera počinju unutar JavaScript bloka: setTimeout sa kašnjenjem od 10ms i setInterval sa istim kašnjenjem. Ovisno o tome kada se tajmer pokrene, aktivirat će se u trenutku kada još nismo završili prvi blok koda. Imajte na umu, međutim, da se ne pokreće odmah (ovo nije moguće zbog jednog navoja). Umjesto toga, odgođena funkcija se stavlja u red čekanja i izvršava se u sljedećem dostupnom trenutku.

    Takođe, tokom izvršavanja prvog JavaScript bloka dolazi do klika mišem. Rukovalac za ovaj asinhroni događaj (a on je asinhroni jer ga ne možemo predvideti) ne može se izvršiti direktno u ovom trenutku, tako da takođe završava u redu, kao i tajmer.

    Nakon što se izvrši prvi blok JavaScript koda, pretraživač postavlja pitanje: „Šta čeka da se izvrši?“ IN u ovom slučaju Rukovalac klika mišem i tajmer su u stanju čekanja. Pretraživač odabire jedan od njih (upravljač klikovima) i izvršava ga. Tajmer će čekati sljedeći raspoloživi dio vremena u redu za izvršavanje.

    Imajte na umu da se aktivira prvi intervalni povratni poziv dok se obrađivač klikova mišem izvršava. Baš kao i tajmer-povratni poziv, bit će u redu čekanja. Međutim, imajte na umu da kada se interval ponovo pokrene (dok je tajmer-povratni poziv pokrenut), on će biti uklonjen iz reda čekanja. Ako su svi intervalni povratni pozivi stavljeni u red dok se izvršavao veliki komad koda, to bi rezultiralo gomilom funkcija koje čekaju da budu pozvane, bez perioda kašnjenja između njih do završetka izvršavanja lijevo u redu prije nego što dodate još jednu u red.

    Dakle, možemo posmatrati slučaj kada se treće aktiviranje interval-callback-a poklopi sa trenutkom kada je već izvršeno. Ovo ilustruje važnu tačku: intervalima nije važno šta se trenutno izvodi, oni će biti dodati u red bez obzira na period kašnjenja između izvršenja.

    Konačno, nakon što se završi drugi interval povratnog poziva, vidjet ćemo da nema više ništa za JavaScript motor da izvrši. To znači da pretraživač ponovo čeka da se dogode novi asinhroni događaji. Ovo će se dogoditi na oznaci od 50 ms, gdje će intervalni povratni poziv ponovo raditi. U ovom trenutku neće moći ništa da ga blokira, tako da će odmah proraditi.

    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 ekvivalentne, ali u stvarnosti nisu. Kod koji koristi setTimeout uvijek će imati kašnjenje od najmanje 10 ms nakon prethodnog poziva (može biti više, ali nikad manje), dok će kod koji koristi setInterval biti pozvan svakih 10 ms, bez obzira na to kada se prethodni poziv dogodio.
    Da sumiramo sve gore rečeno:
    - Funkcije setTimeout i setInterval se izvode fundamentalno drugačije u asinkronom kodu,
    - Ako se tajmer ne može izvršiti u trenutno, bit će odgođen do sljedeće tačke izvršenja (koja će biti duža od željenog kašnjenja),
    - Intervali (setInterval) se mogu izvršavati jedan za drugim bez odlaganja ako njihovo izvršavanje traje duže od navedenog odlaganja.

    Sve ovo je izuzetno važne informacije za razvoj. Poznavanje načina na koji JavaScript motor radi, posebno sa mnogo asinhronih događaja (što se često dešava), postavlja sjajnu osnovu za izgradnju naprednih aplikacija.

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

    Gotovo sve implementacije JavaScripta imaju interni planer tajmera koji vam omogućava da zakažete poziv funkcije nakon određenog vremenskog perioda.

    Konkretno, ova funkcija je podržana u pretraživačima i na Node.JS serveru.

    setTimeout

    sintaksa:

    var timerId = setTimeout(func/code, delay[, arg1, arg2...])

    Parametri:

    • func/code
      • Funkcija ili red koda koji se izvršava.
      • Niz se održava radi kompatibilnosti i ne preporučuje se.
    • func
      • Latencija u milisekundama, 1000 milisekundi jednako je 1 sekundi.
    • arg1, arg2…
      • Argumenti za prosljeđivanje funkciji. Nije podržano u IE9-.
      • Funkcija će se izvršiti nakon vremena navedenog u parametru kašnjenja.

    Na primjer, sljedeći kod će pokrenuti upozorenje ("Zdravo") nakon jedne sekunde:

    funkcija func () ( alert("Zdravo"); ) setTimeout(func, 1000);

    Ako je prvi argument string, onda tumač kreira anonimnu funkciju iz tog niza.

    Odnosno, ovaj unos radi potpuno isto:

    SetTimeout("alert("Hello")" , 1000 );

    Umjesto toga koristite anonimne funkcije:

    SetTimeout(function () ( alert("Hello") ), 1000 );

    Parametri za funkciju i kontekst

    Sve u svemu moderni pretraživači S obzirom na IE10, setTimeout vam omogućava da specificirate parametre funkcije.

    Primjer ispod će ispisati "Zdravo, ja sam Vasya" svuda osim IE9-:

    funkcija sayHi (ko) ( alert("Bok, ja sam " + tko); ) setTimeout(sayHi, 1000 , "Vasya");

    ...Međutim, u većini slučajeva nam je potrebna podrška starog IE-a, a on vam ne dozvoljava da navedete argumente. Stoga, da bi ih prenijeli, oni obavijaju poziv u anonimnu funkciju:

    function sayHi (who) ( alert("Bok, ja sam " + tko); ) setTimeout(function () ( sayHi("Vasya") ), 1000 );

    Pozivanje setTimeout ne propušta ovaj kontekst.

    Konkretno, pozivanje metode objekta preko setTimeout će raditi u globalnom kontekstu. To može dovesti do netačnih rezultata.

    Na primjer, pozovimo user.sayHi() nakon jedne sekunde:

    funkcija Korisnik (id) funkcija () ( upozorenje(ovaj .id); ); ) var korisnik = novi korisnik(12345); setTimeout(user.sayHi, 1000 ); // očekuje se 12345, ali će ispisati "nedefinirano"

    Pošto će setTimeout pokrenuti funkciju user.sayHi u globalnom kontekstu, neće imati pristup objektu preko ovog .

    Drugim riječima, ova dva poziva za setTimeout rade istu stvar:

    // (1) jedan red setTimeout(user.sayHi, 1000); // (2) ista stvar u dva retka var func = user.sayHi; setTimeout(func, 1000 );

    Srećom, i ovaj problem se lako rješava kreiranjem posredne funkcije:

    funkcija Korisnik (id) ( ovaj .id = id; ovaj .sayHi = funkcija () ( upozorenje(ovaj .id); ); ) var korisnik = novi korisnik(12345); setTimeout(function () ( user.sayHi(); ), 1000 );

    Funkcija omotača se koristi za prosljeđivanje argumenata unakrsnom pregledniku i očuvanje konteksta izvršavanja.

    Otkazivanje izvršenja

    Funkcija setTimeout vraća timerId koji se može koristiti za otkazivanje akcije.

    sintaksa:

    ClearTimeout(timerId)

    U sljedećem primjeru postavili smo vremensko ograničenje, a zatim izbrisali (predomislili smo se). Kao rezultat toga, ništa se ne dešava.

    var timerId = setTimeout(function () ( alert(1)), 1000); clearTimeout(timerId); setInterval

    Metoda setInterval ima sintaksu sličnu setTimeout.

    var timerId = setInterval(func/code, delay[, arg1, arg2...])

    Značenje argumenata je isto. Ali, za razliku od setTimeout , on ne pokreće funkciju jednom, već je redovno ponavlja u određenom vremenskom intervalu. Izvršenje možete zaustaviti pozivom:

    ClearInterval(timerId)

    Sljedeći primjer, kada se pokrene, prikazat će poruku svake dvije sekunde dok ne kliknete na dugme Stop:

    var i = 1 ;

    var timer = setInterval(function () (alert(i++)), 2000);

    Stavljanje u red i preklapanje poziva u setInterval

    Poziv setInterval(funkcija, kašnjenje) uzrokuje da se funkcija izvrši u navedenom vremenskom intervalu. Ali ovdje postoji jedna suptilnost.

    Zapravo, pauza između poziva je manja od navedenog intervala.

    Odnosno, pretraživač inicira pokretanje funkcije uredno svakih 100ms, ne uzimajući u obzir vrijeme izvršavanja same funkcije.

    Dešava se da izvršavanje funkcije traje duže od kašnjenja. Na primjer, funkcija je složena, ali kašnjenje je malo. Ili funkcija sadrži naredbe upozorenja/potvrde/prompta koje blokiraju nit izvršenja. Ovdje stvari počinju da postaju zanimljive.

    Ako se funkcija ne može pokrenuti jer je pretraživač zauzet, ona će biti stavljena u red čekanja i izvršena čim se pretraživač oslobodi.

    Slika ispod ilustruje šta se dešava sa funkcijom kojoj je potrebno mnogo vremena da se izvrši.

    Poziv funkcije koji je pokrenuo setInterval dodaje se u red čekanja i javlja se odmah kada je to moguće:

    Drugo pokretanje funkcije događa se odmah nakon završetka prvog:

    Izvršenje se ne stavlja u red čekanja više od jednom.

    Ako nekoj funkciji treba duže da se izvrši od nekoliko zakazanih izvršavanja, ona će i dalje jednom stajati u redu čekanja. Dakle, nema "akumulacije" lansiranja.

    Na slici ispod, setInterval pokušava izvršiti funkciju za 200ms i stavlja poziv u red čekanja. Na 300 ms i 400 ms tajmer se ponovo budi, ali se ništa ne dešava.

    Pozivanje setInterval(funkcija, kašnjenje) ne garantuje stvarno kašnjenje između izvršavanja.

    Postoje slučajevi kada je stvarno kašnjenje veće ili manje od navedenog. Općenito, nije činjenica da će doći do barem nekog kašnjenja.

    Ponavljanje ugniježđenog setTimeouta

    U slučajevima kada nije potrebno samo redovno ponavljanje, već je potrebno kašnjenje između pokretanja, setTimeout se koristi za ponovno postavljanje svaki put kada se funkcija izvršava.

    Ispod je primjer koji izdaje upozorenje s intervalima od 2 sekunde između njih.

    var i = 1;

    var timer = setTimeout(funkcija run () (alert(i++); timer = setTimeout(run, 2000); ), 2000);

    Vremenska linija izvršavanja će imati fiksna kašnjenja između pokretanja. Ilustracija za kašnjenje od 100ms:

    Minimalno kašnjenje tajmera

    Tajmer pretraživača ima najmanju moguću latenciju. Ona varira od približno nula do 4 ms u modernim pretraživačima. Kod starijih može biti duže i dostići 15ms.

    Prema standardu, minimalno kašnjenje je 4 ms. Dakle, nema razlike između setTimeout(..,1) i setTimeout(..,4) .

  • Ponašanje setTimeout i setInterval nulte kašnjenja je specifično za pretraživač.
  • U Internet Exploreru, nulto kašnjenje setInterval(.., 0) neće raditi. Ovo se posebno odnosi na setInterval, tj. setTimeout(.., 0) radi dobro.
  • Stvarna frekvencija okidača

    Okidanje može biti mnogo rjeđe. U nekim slučajevima kašnjenje ne mora biti 4 ms, već 30 ms ili čak 1000 ms.

    Većina pretraživača (prvenstveno za desktop) nastavlja da izvršava setTimeout / setInterval čak i ako je kartica neaktivna. Istovremeno, određeni broj njih (Chrome, FF, IE10) smanjuje minimalnu frekvenciju tajmera na 1 put u sekundi. Ispostavilo se da će tajmer raditi na kartici "pozadina", ali rijetko.

    Kada rade na bateriju, na laptopu, pretraživači također mogu smanjiti frekvenciju kako bi rjeđe izvršavali kod i štedjeli energiju baterije. IE je posebno poznat po tome. Smanjenje može doseći nekoliko puta, ovisno o postavkama. Ako je opterećenje CPU-a previsoko, JavaScript možda neće moći obraditi tajmere na vrijeme. Ovo će preskočiti neke setInterval pokretanja.

    Zaključak: frekvenciju od 4ms vrijedi fokusirati, ali ne biste trebali računati na nju.

    Izlaz intervala na konzolu Kod koji broji vremenske intervale između poziva izgleda otprilike ovako:

    var timeMark = novi datum; setTimeout(function go () ( var diff = new Date - timeMark; // ispis sljedeće odgode na konzolu umjesto stranice konzole .log(diff); // zapamtite vrijeme na samom kraju, // za mjerenje kašnjenje između poziva timeMark = novi datum setTimeout(go, 100), 100); Trik je setTimeout(func, 0)

    Ovaj trik je dostojan ulaska u anale JavaScript hakova.

    Funkcija je umotana u setTimeout(func, 0) ako želite da je pokrenete nakon završetka trenutne skripte.

    Stvar je u tome što setTimeout nikada ne izvršava funkciju odmah. On samo planira njegovu implementaciju. Ali JavaScript interpreter će početi da izvršava planirane funkcije tek nakon što se trenutna skripta izvrši.

    Prema standardu, setTimeout ionako ne može izvršiti funkciju s kašnjenjem od 0 Kao što smo ranije rekli, kašnjenje će obično biti 4 ms. Ali glavna stvar ovdje je da će se izvršenje u svakom slučaju dogoditi nakon izvršenja trenutnog koda.

    na primjer:

    var rezultat; funkcija showResult () ( upozorenje(rezultat); ) setTimeout(showResult, 0); rezultat = 2 *2 ; // će dati 4 Total

    Metode setInterval(func, delay) i setTimeout(func, kašnjenje) omogućavaju vam da redovno pokrećete func/jednom u svakoj milisekundi kašnjenja.

    Obje metode vraćaju ID tajmera. Koristi se za zaustavljanje izvršavanja pozivanjem clearInterval/clearTimeout.

    | | setInterval | setTimeout | || ----------- | ---------- | | Timing | Poziv je strogo na tajmeru. Ako je prevodilac zauzet, jedan poziv je u redu čekanja. Vrijeme izvršenja funkcije se ne uzima u obzir, tako da vremenski interval od kraja jednog pokretanja do početka drugog može varirati. | Rekurzivni poziv na setTimeout se koristi umjesto setInterval gdje je potrebna fiksna pauza između izvršenja. | | Kašnjenje | Minimalno kašnjenje: 4ms. | Minimalno kašnjenje: 4ms. | | Karakteristike pretraživača | Latencija 0 ne radi u IE | U Operi, nulta latencija je ekvivalentna 4 ms, a ostala kašnjenja se obrađuju precizno, uključujući nestandardne 1 ms, 2 ms i 3 ms. |

    © 2024 ermake.ru -- O popravci računara - Informativni portal