Toista toiminnot määritetyllä JavaScript-aikavälillä. Esimerkkejä jQuery-funktiosta setTimeout()

Kotiin / Teknologiat

Window- ja Worker-liitännöissä tarjottava setInterval()-menetelmä kutsuu toistuvasti funktiota tai suorittaa koodinpätkän kiinteällä aikaviiveellä kunkin kutsun välillä.

Se palauttaa intervallitunnuksen, joka yksilöi intervallin, joten voit poistaa sen myöhemmin kutsumalla clearInterval() . Tämän menetelmän määrittää WindowOrWorkerGlobalScope-miksiini. Syntaksi = var intervalID soveltamisalaan .setInterval(, func, [viive, arg1, ...]); Syntaksi = var intervalID soveltamisalaan arg2, func koodi ); Parametrit func Toiminto, joka suoritetaan joka millisekunnin viive. Funktiolle ei välitetä argumentteja, eikä paluuarvoa odoteta. code Valinnaisen syntaksin avulla voit sisällyttää merkkijonon funktion sijasta, joka käännetään ja suoritetaan joka millisekunnin viive. Tämä syntaksi on .setInterval( ei suositella

samoista syistä, jotka tekevät eval():n käytöstä turvallisuusriskin. viive Aika millisekunteina (sekunnin tuhannesosina), jonka ajastimen tulee viivästää määritetyn toiminnon tai koodin suoritusten välillä. Katso alta lisätietoja sallituista viivearvoista. arg1, ..., argN Valinnainen Lisäargumentit, jotka välitetään funktion määrittelemään funktioon

kun ajastin umpeutuu.

Huomautus: Lisäargumenttien välittäminen parametrille setInterval() ensimmäisessä syntaksissa ei toimi

Internet Explorer

9 ja aikaisemmin. Jos haluat ottaa tämän toiminnon käyttöön kyseisessä selaimessa, sinun on käytettävä monitäyttöä (katso kohta).

Palautusarvo

Palautettu intervalID on numeerinen, nollasta poikkeava arvo, joka identifioi setInterval() -kutsun luoman ajastimen; tämä arvo voidaan siirtää aikakatkaisun peruuttamiseksi.

Var intervalID = window.setInterval(myCallback, 500, "Parametri 1", "Parameter 2"); function myCallback(a, b) ( // Koodisi tässä // Parametrit ovat täysin valinnaisia. console.log(a); console.log(b); )

Esimerkki 2: Kahden värin vuorottelu

Seuraava esimerkki kutsuu flashtext()-funktiota kerran sekunnissa, kunnes Stop-painiketta painetaan.

setInterval/clearInterval esimerkki var nIntervId;

funktio changeColor() ( nIntervId = setInterval(flashText, 1000); ) function flashText() ( var oElem = document.getElementById("my_box"); oElem.style.color = oElem.style.color == "punainen"? " blue" : "red"; // oElem.style.color == "red" ? "blue" : "red" on kolmiosainen operaattori. ) Funktio stopTextColor() ( clearInterval(nIntervId); )

Hei maailma

Stop

Esimerkki 3: Kirjoituskonesimulaatio

Seuraava esimerkki simuloi kirjoituskonetta tyhjentämällä ensin ja kirjoittamalla sitten hitaasti sisältöä NodeList-luetteloon, joka vastaa tiettyä valitsinryhmää.< 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-kirjoituskone - MDN-esimerkkifunktio Kirjoituskone (sSelector, nRate) ( toiminto clean () ( clearInterval(nIntervId); bTyping = false; bStart = true; oCurrent = null; aSheets.length = nIdx = 0; ) funktion vieritys (oSheet, nPosheet , bEraseAndStop) ( if (!oSheet.hasOwnProperty("parts") || aMap.length

CopyLeft 2012, Mozilla Developer Network

[ Pelaa | Tauko | Lopeta]

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 ja lacus ultricies vitae facilisis nisi fringilla. in tincidunt tincidunt tincidunt.

JavaScript kirjoituskone
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, erot 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 posuere. Pellentesque sit amet metus a turpis lobortis tempor eu vel tortor. Cras sodales eleifend interdum.

Duis lobortis sapien quis nisl luctus porttitor. Tempor semper libero, eu tincidunt dolor eleifend sit amet. Ut muualle velit in dolor tincidunt rhoncus non non diam. Morbi auctor ornare orci, non euismod felis gravida, muualle luokittelematon. Curabitur elementum nisi a eros rutrum muualle luokittelematon blandit diam placerat. Aenean tincidunt risus ut nisi consectetur cursus. Ut vitae quam elit. Donec dignissim est in quam tempor consquat. Aliquam aliquam diam non felis convallis suscipit. Nolla facilisi. Donec lacus risus, dignissim et fringilla et, egestas vel eros. Duis malesuada accumsan dui, ja 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 muualle 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.

Takaisinsoittoargumentit

Kuten aiemmin on todettu, Internet Explorerin versiot 9 ja sitä vanhemmat eivät tue argumenttien välittämistä takaisinsoittofunktiolle setTimeout()- tai setInterval()-funktiossa. Seuraava IE-kohtainen koodi näyttää menetelmän tämän rajoituksen voittamiseksi. Käytä yksinkertaisesti lisäämällä seuraava koodi komentosarjasi alkuun.

/*\ |*| |*| IE-spesifinen monitäyttö, joka mahdollistaa mielivaltaisten argumenttien siirtämisen |*| JavaScript-ajastimien takaisinsoittotoiminnot (HTML5-standardin syntaksi)..setInterval |*| https://site/User:fusionchess |*| |*| Syntaksi: |*| var timeoutID = window.setTimeout(func, delay[, arg1, arg2, ...]); |*| var aikakatkaisuID = window.setTimeout(koodi, viive); |*| var intervalID = window.setInterval(funktio, viive[, arg1, arg2, ...]); |*| var intervalID = ikkuna.setInterval(koodi, viive); |*| \*/ if (document.all && !window.setTimeout.isPolyfill) ( var __nativeST__ = window.setTimeout; window.setTimeout = funktio (vCallback, nDelay /*, argumentToPass1, argumentToPass2 jne. */) ( var aArgs = Array .prototype.slice.call(arguments, 2); return __nativeST__(vCallback instanceof Function () ( vCallback.apply(null, aArgs); ): vCallback, nDelay ); ( var __nativeSI__ = window.setInterval; window.setInterval = funktio (vCallback, nDelay /*, argumentToPass1, argumentToPass2 jne. */) ( var aArgs = Array.prototype. slice.call(arguments, 2); return __nativeSI__(vCallback Funktio () ( vCallback.apply(null, aArgs); ) : vCallback, nDelay );

Toinen mahdollisuus on käyttää anonyymiä toimintoa takaisinsoittoon, vaikka tämä ratkaisu onkin hieman kalliimpi. Esimerkki:

Muutt-intervalliID = setInterval(function() ( myFunc("yksi", "kaksi", "kolme"); ), 1000);

var intervalID = setInterval(funktio(arg1) ().bind(määrittämätön, 10), 1000);

Ei-aktiiviset välilehdet Vaatii Gecko 5.0:n (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)

Alkaen Gecko 5.0:sta (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2) välilehdet suljetaan niin, että ne käynnistyvät useammin kuin kerran sekunnissa ei-aktiivisilla välilehdillä.

"Tämä" ongelma

Kun välität menetelmän setInterval()-funktiolle tai jollekin muulle funktiolle, se kutsutaan väärällä arvolla. Tämä ongelma on selitetty yksityiskohtaisesti JavaScript-viittauksessa.

Selitys

MyArray = ["nolla", "yksi", "kaksi"]; myArray.myMethod = funktio (sProperty) ( alert(arguments.length > 0 ? this : this); ); myArray.myMethod(); // tulostaa "zero,one,two" myArray.myMethod(1); // tulostaa "yksi" setTimeout(myArray.myMethod, 1000); // tulostaa "" 1 sekunnin kuluttua setTimeout(myArray.myMethod, 1500, "1"); // tulostaa "undefined" 1,5 sekunnin kuluttua // "tämän" objektin välittäminen .call-komennolla ei toimi // koska tämä muuttaa itse setTimeoutin arvoa // samalla kun haluamme muuttaa tämän arvoa myArrayn sisällä .myMethod // itse asiassa se on virhe, koska setTimeout-koodi odottaa tämän olevan ikkunaobjekti: setTimeout.call(myArray, myArray.myMethod, 2000) // virhe: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Laiton toiminta Wrapped-prototyyppiobjektissa"Native); setTimeout.call(myArray, myArray.myMethod, 2500, 2); // sama virhe

Kuten näet, ei ole tapoja siirtää tätä objektia takaisinkutsutoimintoon vanhassa JavaScriptissä.

Mahdollinen ratkaisu

Mahdollinen tapa ratkaista "tämä" ongelma on korvata kaksi natiivia setTimeout() tai setInterval() globaalia funktiota kahdella ei-syntyperäinen ne, jotka mahdollistavat niiden kutsumisen Function.prototype.call-menetelmän kautta. Seuraava esimerkki näyttää mahdollisen korvaavan:

// Ota käyttöön "tämä"-objektin kulku JavaScript-ajastimien kautta. var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval; window.setTimeout = funktio (vCallback, nDelay /*, argumentToPass1, argumentToPass2 jne. */) ( var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2); return __nativeST__(vCallback-instanssi Function ? -funktiosta () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay ); window.setInterval = funktio (vCallback, nDelay /*, argumentToPass1, argumentToPass2 jne. */) ( var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2); return __nativeSI__(vCallback-instanssi funktiosta ? () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay );

Nämä kaksi korvausta mahdollistavat myös mielivaltaisten argumenttien HTML5-standardin siirtämisen IE:n ajastimien takaisinsoittotoimintoihin. Joten niitä voidaan käyttää ei-standardin mukainen myös polyfillit. Katso a standardin mukainen polyfill

Uusi ominaisuustesti:

MyArray = ["nolla", "yksi", "kaksi"]; myArray.myMethod = funktio (sProperty) ( alert(arguments.length > 0 ? this : this); ); setTimeout(hälytys, 1500, "Hei maailma!"); // setTimeout- ja setInterval-standardien käyttö säilyy, mutta... setTimeout.call(myArray, myArray.myMethod, 2000); // tulostaa "zero,one,two" 2 sekunnin kuluttua setTimeout.call(myArray, myArray.myMethod, 2500, 2); // tulostaa "kaksi" 2,5 sekunnin kuluttua

Monimutkaisempaa, mutta silti modulaarista versiota varten ( Daemon) katso JavaScript Daemons Management . Tämä monimutkaisempi versio on vain suuri ja skaalautuva kokoelma menetelmiä Daemon rakentaja. Kuitenkin Daemon konstruktori itsessään on vain sen klooni MiniDaemon lisätyllä tuella init ja käynnistyy funktiot, jotka on ilmoitettu ilmentymisen aikana demoni. Joten MiniDaemon kehys on edelleen suositeltava tapa yksinkertaisille animaatioille , koska Daemon ilman sen menetelmäkokoelmaa on pohjimmiltaan sen klooni.

minidaemon.js /*\ |*| |*| :: MiniDaemon:: |*| |*| Versio #2 - 26. syyskuuta 2014.setInterval |*| https://site/User:fusionchess |*| https://github.com/madmurphy/minidaemon.js |*| |*| Tämä kehys on julkaistu GNU Lesser General Public License -lisenssillä, versio 3 tai uudempi. |*| http://www.gnu.org/licenses/lgpl-3.0.html |*| \*/-funktio MiniDaemon (oOmistaja, fTask, nRate, nLen) (if (!(tämä && tämä MiniDaemonin esiintymä)) ( 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 = Ääretön;< 1: this.INDEX + 1 >this.length; ); MiniDaemon.prototype.synchronize = toiminto () ( if (this.PAUSED) ( return; ) clearInterval(this.SESSION); this.SESSION = setInterval(MiniDaemon.forceCall, this.rate, this); ); MiniDaemon.prototype.pause = toiminto () ( clearInterval(this.SESSION); this.PAUSED = true; ); MiniDaemon.prototype.start = funktio (bReverse) ( var bBackw = Boolean(bReverse); if (this.BACKW === bBackw && (this.isAtEnd() || !this.PAUSED)) ( return; ) this.BACKW = bBackw; this.PAUSED = false this.synchronize();

MiniDaemon välittää argumentit takaisinsoittofunktiolle. Jos haluat käsitellä sitä selaimilla, jotka eivät tue tätä ominaisuutta, käytä jotakin yllä ehdotetuista menetelmistä.

Syntaksi

var myDaemon = new MiniDaemon( tämä objekti, takaisinsoitto[ , korko [, pituus]]);

Kuvaus Käyttöohjeet

SetInterval()-funktiota käytetään yleisesti asettamaan viive funktioille, jotka suoritetaan yhä uudelleen, kuten animaatioille. Voit peruuttaa intervallin käyttämällä WindowOrWorkerGlobalScope.clearInterval() -funktiota.

Jos haluat, että toimintosi kutsutaan kerran määritetyn viiveen jälkeen käytä .

Viivästymisrajoitukset

On mahdollista, että aikavälit ovat sisäkkäisiä; toisin sanoen setInterval():n takaisinkutsu voi puolestaan ​​kutsua setInterval():n käynnistääkseen toisen intervallin, vaikka ensimmäinen on vielä käynnissä. Tämän mahdollisen vaikutuksen vähentämiseksi suorituskykyä, kun aikavälit ovat sisäkkäisiä yli viiden tason syvyydelle, selain pakottaa automaattisesti 4 ms:n vähimmäisarvon. Yritykset määrittää alle 4 ms:n arvo syvälle sisäkkäisissä kutsuissa asetetaan 4 ms:iin.

Selaimet voivat pakottaa tietyissä olosuhteissa jopa tiukempia vähimmäisarvoja aikavälille, vaikka näiden ei pitäisi olla yleisiä. Huomaa myös, että todellinen aika, joka kuluu takaisinkutsujen välillä, voi olla pidempi kuin annettu viive; Katso esimerkkejä kohdassa WindowOrWorkerGlobalScope.setTimeout() määritettyä pitempien viivästysten syyt.

Varmista, että suorituksen kesto on lyhyempi kuin intervallitaajuus

Jos on mahdollista, että logiikkasi suorittaminen saattaa kestää kauemmin kuin aikaväli, on suositeltavaa kutsua nimettyä funktiota rekursiivisesti käyttämällä setTimeout() . Jos esimerkiksi käytät setInterval()-komentoa etäpalvelimen kyselyyn 5 sekunnin välein, verkon viive, vastaamaton palvelin ja monet muut ongelmat voivat estää pyyntöä suorittamasta pyyntöä loppuun määrätyssä ajassa. Näin ollen saatat löytää itsesi jonossa XHR-pyynnöistä, jotka eivät välttämättä palaa järjestyksessä.

Ohjelmoinnissa komentosarjakielillä on ajoittain tarpeen luoda tauko - keskeyttää ohjelman suoritus hetkeksi ja jatkaa sitten työskentelyä. Esimerkiksi VBS- ja PHP-skripteissä seuraavat menetelmät ovat mahdollisia:

VBS: wscript.sleep 1500 (pysähdy 1,5 sekunniksi)

PHP: uni(10); (pysähdy 10 sekunniksi)

Tällaisten taukojen aikana ajonaikainen järjestelmä (PHP tai VBS) ei tee mitään. Kehittäjä, joka yrittää intuitiivisesti käyttää jotain vastaavaa Javascriptissä, yllättyy ikävästi. Yleinen virhe kun yrität luoda tauon Javascriptissä, se näyttää tältä:

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

Ajattelet, että kun silmukan aikana tulee vuoro piirtää seuraava numero, setTimeout lopettaa rehellisesti Javascriptin toiminnan, odota 0,9 sekuntia, lisää haluamasi numero syöttökentän loppuun ja jatkaa sitten työskentelyä. Mutta todellisuudessa tämä ei ole totta: setInterval ja setTimeout Javascriptissä vain viivästyttävät suluissa määritellyn toiminnon (tai funktion) suorittamista. Esimerkissämme tapahtuu seuraavaa:

  • i = 1;
  • viive numeron "1" lisäämistä syöttökenttään 0,9 sekuntia;
  • Välittömästi tämän ongelman asettamisen jälkeen sykli jatkuu: i=2;
  • viive numeron "2" lisäämistä syöttökenttään 0,9 sekuntia;
  • Välittömästi tarkoittaa esimerkiksi 1 ms (eli suhteettoman pientä 900 ms:aan verrattuna): silmukka tekee työnsä lähes välittömästi luoden useita lykättyjä tehtäviä samasta ajankohdasta. Tämä tarkoittaa, että kaikki odottavat "piirustus" tehtävät suoritetaan lähes samaan aikaan ilman taukoja uusien numeroiden lisäämisen välillä. Jakso alkaa; kaikki jäätyy 0,9 s; ja shirr - kaikki numerot ammutaan peräkkäin peräkkäin.

    Kuinka käyttää setTimeout oikein tällaisessa tapauksessa? Se on monimutkaista. Sinun täytyy kutsua toiminto rekursiivisesti(funktiosta sama toiminto) ja jotta tämä prosessi ei olisi loputon, aseta pysäytysehto (esimerkiksi tulostettavan numeron koko):

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

    Ja muuttuja i on alustettava funktion ulkopuolella - esimerkiksi näin:

    Nyt kaikki toimii kuten pitääkin (vähensimme viiveaikaa 0,9 s:sta 0,4 s:iin). Mutta tällaisiin tehtäviin on loogisempaa käyttää setIntervalia setTimeoutin sijaan (vaikka tämä vaatii kaksi toimintoa):

    Funktio besttest() ( window.i = 0 window.timer1 = window.setInterval("draw()", 400) ) funktio draw() ( document.getElementById("test3").arvo += ++i if (i >= 9) clearInterval(window.timer1) )

    Javascirpt setInterval -menetelmän erikoisuus on, että se ei läpäise "itsekseen" se täytyy pysäyttää erityisellä clearInterval-menetelmällä. Ja jotta olisi selvää, mitä tarkalleen lopettaa, lykätyn toiminnon tehtävälle on määritetty erityinen tunniste - ajastin: window.timer1 = window.setInterval(...) .

    Tunnisteita voidaan määrittää myös setTimeout-menetelmällä luoduille tehtäville. Kaikkien ajastintunnusten on erotettava toisistaan ​​(ainutlaatuiset nykyisessä selainikkunassa). Sitten voit luoda ikkunaan useita erilaisia ​​tehtäviä, jotka käyttävät viivästettyjä toimintoja, ja nämä tehtävät suoritetaan rinnakkain (ikään kuin samanaikaisesti, jos tietokoneella on tarpeeksi resursseja), mikä on periaatteessa mahdotonta PHP:ssä tai VBS:ssä.

    Tässä on esimerkki sivusta, jossa useita Javascript-ajastimia on käynnissä samanaikaisesti: setinterval.htm (Javascript-funktiot setinterval.js-tiedostossa). Kaikki sivuajastimet (paitsi valikko) voidaan pysäyttää Esc-näppäimellä. Kaikki esimerkkiajastimet perustuvat "luonnolliseen" (eikä abstraktiin i++) lähtölaskentaan - aikaan tai etäisyyteen. Kaikki "kellot" on erityisesti desynkronoitu (selvyyden vuoksi). Etäisyysriippuvaisia ​​ajastimia käytetään "indikaattorissa" ja pudotusvalikossa ("pull-out").

    Pudotusvalikko

    Liukuvalikkomme on itse asiassa liukuva ("otsikon" alta): elementtien väliin on jätetty erityisesti rakoja, jotta näet kuinka se liukuu ulos. Yllättäen kävi ilmi, että eripituisten listojen poistumista ei voitu tehdä yhtä sujuvasti - luultavasti tietokoneen heikon suorituskyvyn vuoksi (AMD Athlon 999 MHz).

    On aivan ilmeistä, että kauneuden ja harmonian kannalta on välttämätöntä, että eri valikkokohtien luettelot näkyvät samanaikaisesti. Eli pitkien listojen pitäisi pudota pois enemmän suuri nopeus, lyhyemmät - pienemmällä nopeudella. Vaikuttaa siltä, ​​että tämä voitaisiin toteuttaa näin:

  • Asetamme "lähtö" kokonaisajaksi esimerkiksi 200 ms.
  • Jos pudotusvalikon korkeus on 20 px, on selvää, että voimme siirtää sitä yhden pikselin alaspäin 10 ms:n välein - ja sitten 200 ms:n kuluttua koko lista tulee ulos.
  • Jos pudotusvalikko on 40 pikseliä korkea, meidän on siirrettävä sitä alaspäin yhden pikselin välein, jotta se mahtuisi samaan aikaan.
  • Tämän logiikan mukaan, jos avattava luettelo on 200 pikseliä korkea, meidän pitäisi siirtää sitä yksi pikseliä alaspäin 1 ms välein. Mutta tällainen nopeus ei toimi tietokoneellamme - selaimella ei yksinkertaisesti ole aikaa piirtää luettelon uutta sijaintia millisekunnissa. Kyllä. Javascript onnistuu laskemaan (mitä siellä on laskea?), mutta selaimella (Firefox) ei ole aikaa näyttää. Tyypillinen tilanne netissä.

    Siksi valikon lähtöaikaa on mahdollista tasoittaa enemmän tai vähemmän vain kainalosauvojen avulla, ja on edelleen epäselvää, kuinka tämä toimii enemmän nopea tietokone. Mutta meidän pitäisi luottaa hitaimpaan, eikö niin? Algoritmi (ottamatta huomioon tietokoneen nopeutta) on jotain tällaista:

  • Aseta luettelon tarkastelun kokonaisaika: aika = 224 (ms).
  • Asetamme syklin yhden intervallin minimiajan: viive = 3 (ms).
  • Aseta luettelon siirtämisen vähimmäisaskel: offset = 1 (px).
  • Muutamme kaiken tämän listan korkeudesta riippuen: 1) lisäämme viiveen (välin) aikaa käänteisesti suhteessa korkeuteen ja suoraan verrannollisesti kokonaisaikaaikaan (224:n korkeudella kerroin on 1); 2) jos korkeus on suurempi kuin 40 px, nosta vähimmäisaskelmaa suhteessa korkeuteen. Vakio "40" saatiin kokeellisesti hitaimmalle tietokoneelle. Testit Pentium 4 CPU 2,53 GHz -tietokoneella paljastivat täsmälleen saman määrän - 40. Muuten ajastimet menevät rikki, luettelot menevät rikki.
  • Nyt listat ovat tulossa enemmän tai vähemmän ulos. Enemmän tai vähemmän samanlaisen ajan. setinterval.htm-sivulla.

    Ja tässä tulee Bruce:

    Funktio 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 } } }

    Itse toiminto, joka työntää sisäkkäiset luettelot pois valikosta, on, kuten näemme, hyvin yksinkertainen. Jäljelle jää vain ajaa se jollain tällä rivillä:

    Ts.ajastin1 = setInterval(function())(slide_do(ts, maxtop, offset)), viive)

    No, ennen kuin aloitat, laske vain kaikki nämä maxtop ja offset ja aseta luettelo myös minttop-asentoon. Näin tekee 40 rivin "alustava" slide()-funktio. Ja kaikki yhdessä - tiedostossa setinterval.js. Kyllä, ja tämä paska ei toimi ollenkaan ilman mukana tulevaa tyylitiedostoa

    On erittäin tärkeää ymmärtää, miten JavaScript-ajastimet toimivat. Usein heidän käyttäytymisensä ei vastaa intuitiivista ymmärrystämme monisäikeisyydestä, ja tämä johtuu siitä, että todellisuudessa ne suoritetaan yhdessä säikeessä. Katsotaanpa neljää toimintoa, joilla voimme hallita ajastimia:

    • var id = setTimeout(fn, viive); - Luo yksinkertaisen ajastimen, joka kutsuu tiettyä toimintoa tietyn viiveen jälkeen. Funktio palauttaa yksilöllisen tunnuksen, jolla ajastin voidaan keskeyttää.
    • var id = setInterval(fn, viive); - Samanlainen kuin setTimeout, mutta kutsuu funktiota jatkuvasti tietyin väliajoin (pysähdykseen asti).
    • clearInterval(id);, clearTimeout(id); - Hyväksyy ajastintunnuksen (jokin yllä kuvatuista toiminnoista palauttaa) ja lopettaa takaisinkutsun suorittamisen"a.
    Tärkein huomioitava ajatus on, että ajastimen viivejakson tarkkuutta ei taata. Aluksi selain suorittaa kaikki asynkroniset JavaScript-tapahtumat yhdessä säikeessä (kuten hiiren napsautukset tai ajastimet) ja vain silloin, kun on tapahtuman vuoro. Tämän osoittaa parhaiten seuraava kaavio:

    Tämä kuva sisältää melko paljon tietoa, mutta sen ymmärtäminen antaa sinulle paremman käsityksen JavaScriptin asynkronian toiminnasta. Tämä kaavio esittää aikaa pystysuunnassa millisekunteina, siniset lohkot näyttävät suoritetut JavaScript-koodilohkot. Esimerkiksi ensimmäinen lohko suoritetaan keskimäärin 18 ms:ssa, hiiren napsautus estää suorituksen noin 11 ms jne.

    JavaScript voi suorittaa vain yhden koodinpalan (suorituksen yksisäikeisen luonteen vuoksi), joista jokainen estää muiden asynkronisten tapahtumien suorittamisen. Tämä tarkoittaa, että kun tapahtuu asynkroninen tapahtuma (kuten hiiren napsautus, ajastinkutsu tai XMLHttp-pyynnön suorittaminen), se lisätään jonoon ja suoritetaan myöhemmin (toteutus vaihtelee tietysti selaimittain, mutta sovitaan kutsua sitä "jonoksi").

    Aluksi kuvitellaan, että JavaScript-lohkon sisällä käynnistyy kaksi ajastinta: setTimeout 10 ms viiveellä ja setInterval samalla viiveellä. Riippuen ajastimen käynnistymisestä, se käynnistyy sillä hetkellä, kun emme ole vielä saaneet ensimmäistä koodilohkoa valmiiksi. Huomaa kuitenkin, että se ei syty heti (tämä ei ole mahdollista yksittäisen kierteen vuoksi). Sen sijaan lykätty toiminto asetetaan jonoon ja suoritetaan seuraavalla käytettävissä olevalla hetkellä.

    Lisäksi ensimmäisen JavaScript-lohkon suorittamisen aikana tapahtuu hiiren napsautus. Tämän asynkronisen tapahtuman (ja se on asynkroninen, koska emme voi ennustaa sitä) käsittelijää ei voida suorittaa suoraan tällä hetkellä, joten sekin päätyy jonoon, kuten ajastin.

    Kun ensimmäinen JavaScript-koodilohko on suoritettu, selain kysyy: "Mikä odottaa suoritusta?" IN tässä tapauksessa Hiiren napsautuskäsittelijä ja ajastin ovat odotustilassa. Selain valitsee niistä yhden (napsautuskäsittelijän) ja suorittaa sen. Ajastin odottaa seuraavaa käytettävissä olevaa aikapalaa suoritusjonossa.

    Huomaa, että kun hiiren napsautuskäsittelijä on suoritettu, ensimmäinen intervalli-takaisinkutsu käynnistyy. Aivan kuten ajastimen takaisinsoitto, se asetetaan jonoon. Huomaa kuitenkin, että kun aikaväli käynnistyy uudelleen (kun ajastimen takaisinkutsu on käynnissä), se poistetaan jonosta. Jos kaikki intervallikutsut asetetaan jonoon suuren koodin suorittamisen aikana, tämä johtaisi siihen, että joukko toimintoja odottaisi kutsua, eikä niiden välillä olisi viivettä. Sen sijaan selaimet odottavat, kunnes toimintoja ei enää ole jonossa ennen kuin lisäät jonoon.

    Siten voimme havaita tapauksen, jossa intervalli-takaisinkutsun kolmas laukaisu osuu hetkeen, jolloin se on jo suoritettu. Tämä havainnollistaa tärkeää asiaa: intervalleilla ei ole väliä mitä parhaillaan käynnissä, ne lisätään jonoon riippumatta suoritusten välisestä viiveestä.

    Lopuksi, kun toinen intervallisoitto on valmis, näemme, ettei JavaScript-moottorilla ole enää mitään suoritettavaa. Tämä tarkoittaa, että selain odottaa jälleen uusia asynkronisia tapahtumia. Tämä tapahtuu 50 ms:n kohdalla, jolloin intervallisoitto toimii taas. Tässä vaiheessa mikään ei estä sitä, joten se toimii välittömästi.

    Katsotaanpa esimerkkiä, joka kuvaa hienosti eroa setTimeout:n ja setIntervalin välillä.
    setTimeout(function())( /* Joku pitkä koodilohko... */ setTimeout(arguments.callee, 10); ), 10);
    setInterval(function())( /* Joku pitkä koodilohko... */ ), 10);

    Nämä kaksi vaihtoehtoa ovat ensi silmäyksellä vastaavia, mutta todellisuudessa ne eivät ole. SetTimeoutia käyttävällä koodilla on aina vähintään 10 ms viive edellisen puhelun jälkeen (se voi olla enemmän, mutta ei koskaan vähemmän), kun taas setInterval-koodia käytetään yleensä 10 ms:n välein, riippumatta siitä, milloin edellinen puhelu tapahtui.
    Tehdään yhteenveto kaikesta yllä sanotusta:
    - Funktiot setTimeout ja setInterval suoritetaan olennaisesti eri tavalla asynkronisessa koodissa,
    - Jos ajastinta ei voida suorittaa sisään tällä hetkellä, se viivästyy seuraavaan suorituspisteeseen (joka on pidempi kuin haluttu viive),
    - Intervallit (setInterval) voidaan suorittaa peräkkäin ilman viivettä, jos niiden suoritus kestää määritettyä viivettä pidempään.

    Kaikki tämä on äärimmäistä tärkeitä tietoja kehitystä varten. JavaScript-moottorin toiminnan tunteminen, erityisesti monien asynkronisten tapahtumien yhteydessä (mitä usein tapahtuu), luo loistavan perustan kehittyneiden sovellusten rakentamiselle.

    Lähde: http://learn.javascript.ru/settimeout-setinterval

    Lähes kaikissa JavaScript-toteutuksissa on sisäinen ajastin, jonka avulla voit ajoittaa funktion kutsuvan tietyn ajan kuluttua.

    Erityisesti tätä ominaisuutta tuetaan selaimissa ja Node.JS-palvelimessa.

    setTimeout

    Syntaksi:

    var timerId = setTimeout(toiminto/koodi, viive[, arg1, arg2...])

    Parametrit:

    • toiminto/koodi
      • Suoritettava funktio tai koodirivi.
      • Merkkijonoa säilytetään yhteensopivuussyistä, eikä sitä suositella.
    • func
      • Latenssi millisekunteina, 1000 millisekuntia on yhtä sekuntia.
    • arg1, arg2…
      • Argumentit, jotka siirretään funktioon. IE9- ei tue.
      • Toiminto suoritetaan viiveparametrissa määritellyn ajan kuluttua.

    Esimerkiksi seuraava koodi laukaisee hälytyksen ("Hei") sekunnin kuluttua:

    function func () ( alert("Hei" ); ) setTimeout(func, 1000 );

    Jos ensimmäinen argumentti on merkkijono, tulkki luo tästä merkkijonosta anonyymin funktion.

    Eli tämä merkintä toimii täsmälleen samalla tavalla:

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

    Käytä sen sijaan anonyymejä toimintoja:

    SetTimeout(funktio () ( hälytys("Hei" ) ), 1000 );

    Toiminnon ja kontekstin parametrit

    Kaiken kaikkiaan nykyaikaiset selaimet IE10:ssä setTimeout antaa sinun määrittää toimintoparametreja.

    Alla oleva esimerkki tulostaa "Hei, olen Vasya" kaikkialla paitsi IE9-:

    function sayHi (who) ( alert("Hei, minä olen " + kuka); ) setTimeout(sayHi, 1000 , "Vasya" );

    ...Kuitenkin useimmissa tapauksissa tarvitsemme tukea vanhalta IE:ltä, eikä se salli argumenttien määrittämistä. Siksi niiden siirtämiseksi he käärivät puhelun anonyymiin toimintoon:

    function sayHi (kuka) ( alert("Hei, minä olen " + kuka); ) setTimeout(function () ( sayHi("Vasya") ), 1000 );

    SetTimeout-kutsu ei läpäise tätä kontekstia.

    Erityisesti objektimetodin kutsuminen setTimeoutin kautta toimii globaalissa kontekstissa. Tämä voi johtaa vääriin tuloksiin.

    Kutsutaan esimerkiksi käyttäjä.sayHi() sekunnin kuluttua:

    function User (id) function () ( hälytys(this .id); ); ) var user = new User(12345); setTimeout(user.sayHi, 1000 ); // odotetaan 12345, mutta tulostaa "undefined"

    Koska setTimeout suorittaa user.sayHi-funktion globaalissa kontekstissa, sillä ei ole pääsyä objektiin tämän kautta.

    Toisin sanoen nämä kaksi setTimeout-kutsua tekevät saman asian:

    // (1) yksi rivi setTimeout(user.sayHi, 1000 ); // (2) sama asia kahdella rivillä var func = user.sayHi; setTimeout(func, 1000 );

    Onneksi tämä ongelma on myös helppo ratkaista luomalla välifunktio:

    function User (id) ( this .id = id; this .sayHi = function () ( alert(this .id); ); ) var user = new User(12345); setTimeout(funktio () ( user.sayHi(); ), 1000 );

    Käärimistoimintoa käytetään argumenttien välittämiseen selaimen välillä ja suorituskontekstin säilyttämiseen.

    Toteutuksen peruuttaminen

    setTimeout-funktio palauttaa timerId:n, jonka avulla toiminto voidaan peruuttaa.

    Syntaksi:

    ClearTimeout(ajastintunnus)

    Seuraavassa esimerkissä asetimme aikakatkaisun ja sitten poistamme (muutimme mieltämme). Tämän seurauksena mitään ei tapahdu.

    var timerId = setTimeout(funktio () ( hälytys(1) ), 1000 ); clearTimeout(ajastintunnus); setInterval

    setInterval-menetelmän syntaksi on samanlainen kuin setTimeout.

    var timerId = setInterval(toiminto/koodi, viive[, arg1, arg2...])

    Argumenttien merkitys on sama. Mutta toisin kuin setTimeout, se ei suorita toimintoa kerran, vaan toistaa sen säännöllisesti tietyin aikavälein. Voit keskeyttää suorituksen soittamalla:

    ClearInterval(ajastintunnus)

    Seuraava esimerkki, kun se suoritetaan, näyttää viestin kahden sekunnin välein, kunnes napsautat Stop-painiketta:

    var i = 1;

    var ajastin = setInterval(funktio () ( hälytys(i++) ), 2000 );

    Puheluiden jonottaminen ja päällekkäisyys setIntervalissa

    Kutsu setInterval(funktio, viive) saa funktion suoritettua tietyllä aikavälillä. Mutta tässä on hienovaraisuutta.

    Itse asiassa puheluiden välinen tauko on pienempi kuin määritetty aikaväli.

    Eli selain käynnistää toiminnon käynnistämisen siististi 100 ms välein ottamatta huomioon itse toiminnon suoritusaikaa.

    Tapahtuu, että toiminnon suorittaminen kestää kauemmin kuin viive. Esimerkiksi toiminto on monimutkainen, mutta viive on pieni. Tai funktio sisältää hälytys-/vahvistus-/kehote-lauseita, jotka estävät suoritussäikeen. Täällä asiat alkavat olla mielenkiintoisia.

    Jos toimintoa ei voida käynnistää, koska selain on varattu, se asetetaan jonoon ja suoritetaan heti, kun selain on vapaa.

    Alla oleva kuva havainnollistaa, mitä tapahtuu toiminnolle, jonka suorittaminen kestää kauan.

    setIntervalin käynnistämä funktiokutsu lisätään jonoon ja tapahtuu heti kun mahdollista:

    Toiminnon toinen käynnistys tapahtuu välittömästi ensimmäisen päättymisen jälkeen:

    Toteutus ei ole jonossa useammin kuin kerran.

    Jos funktion suorittaminen kestää kauemmin kuin useat ajoitetut suoritukset, se joutuu silti jonoon kerran. Laukaisujen "kertymistä" ei siis tapahdu.

    Alla olevassa kuvassa setInterval yrittää suorittaa toiminnon 200 ms:ssa ja asettaa puhelun jonoon. 300 ms ja 400 ms kohdalla ajastin herää uudelleen, mutta mitään ei tapahdu.

    SetInterval(funktio, viive) kutsuminen ei takaa todellista viivettä suoritusten välillä.

    On tapauksia, joissa todellinen viive on suurempi tai pienempi kuin määritetty. Yleisesti ottaen ei ole tosiasia, että viivästyksiä tulee ainakin jonkin verran.

    Toistetaan sisäkkäistä setTimeout

    Tapauksissa, joissa ei vaadita vain säännöllistä toistoa, vaan vaaditaan viivettä ajojen välillä, setTimeoutia käytetään asettamaan uudelleen joka kerta, kun toiminto suoritetaan.

    Alla on esimerkki, joka antaa hälytyksen kahden sekunnin välein.

    var i = 1;

    var ajastin = setTimeout(funktion suoritus () ( hälytys(i++); ajastin = setTimeout(run, 2000 ); ), 2000 );

    Suoritusaikajanalla on kiinteät viiveet ajojen välillä. Kuva 100 ms:n viiveestä:

    Ajastimen minimiviive

    Selaimen ajastimella on pienin mahdollinen latenssi. Se vaihtelee noin nollasta 4 ms:iin nykyaikaisissa selaimissa. Vanhemmissa se voi olla pidempi ja saavuttaa 15 ms.

    Standardin mukaan minimiviive on 4 ms. Joten setTimeout(..,1) ja setTimeout(..,4) välillä ei ole eroa.

  • setTimeout:n ja setIntervalin nollalatenssikäyttäytyminen on selainkohtaista.
  • Internet Explorerissa zero delay setInterval(.., 0) ei toimi. Tämä pätee erityisesti setIntervaliin, ts. setTimeout(.., 0) toimii hyvin.
  • Todellinen laukaisutaajuus

    Liipaisu voi olla paljon harvempi Joissakin tapauksissa viive ei ehkä ole 4 ms, vaan 30 ms tai jopa 1000 ms.

    Useimmat selaimet (pääasiassa pöytätietokoneet) jatkavat setTimeout / setInterval-komentojen suorittamista, vaikka välilehti olisi passiivinen. Samaan aikaan monet niistä (Chrome, FF, IE10) vähentävät ajastimen minimitaajuuden 1 kertaan sekunnissa. Osoittautuu, että ajastin toimii "tausta"-välilehdellä, mutta harvoin.

    Akkuvirralla käytettäessä kannettavaa tietokonetta selaimet voivat myös vähentää taajuutta suorittaakseen koodia harvemmin ja säästääkseen akkuvirtaa. IE on erityisen kuuluisa tästä. Vähennys voi olla useita kertoja asetuksista riippuen. Jos suorittimen kuormitus on liian korkea, JavaScript ei ehkä pysty käsittelemään ajastimia ajoissa. Tämä ohittaa joitakin setInterval-ajoja.

    Johtopäätös: 4 ms:n taajuuteen kannattaa keskittyä, mutta sinun ei pitäisi luottaa siihen.

    Aikavälien tulostaminen konsoliin Koodi, joka laskee puhelujen väliset aikavälit, näyttää tältä:

    var timeMark = uusi päivämäärä; setTimeout(function go () ( var diff = new Date - timeMark; // tulostaa seuraavan viiveen konsoliin sivukonsolin sijaan .log(diff); // muista aika lopussa, // mittaaksesi viive puhelujen välillä timeMark = new Date ; setTimeout(go, 100 ), 100 ); Temppu on setTimeout(func, 0)

    Tämä temppu ansaitsee päästä JavaScript-hakkerointien historiaan.

    Funktio kääritään kohtaan setTimeout(func, 0), jos haluat suorittaa sen nykyisen skriptin päätyttyä.

    Asia on, että setTimeout ei koskaan suorita toimintoa heti. Hän vain suunnittelee sen toteuttamista. Mutta JavaScript-tulkki alkaa suorittaa suunniteltuja toimintoja vasta, kun nykyinen komentosarja on suoritettu.

    Standardin mukaan setTimeout ei voi suorittaa funktiota viiveellä 0 Kuten aiemmin mainittiin, viive on yleensä 4 ms. Mutta tärkeintä tässä on, että suoritus tapahtuu joka tapauksessa nykyisen koodin suorittamisen jälkeen.

    Esimerkiksi:

    var tulos; toiminto showResult () ( hälytys(tulos); ) setTimeout(showResult, 0 ); tulos = 2 * 2 ; // tulostaa 4 Yhteensä

    SetInterval(func, delay) ja setTimeout(func, delay) -menetelmien avulla voit suorittaa funktion säännöllisesti/kerran viivemillisekunnissa.

    Molemmat menetelmät palauttavat ajastimen tunnuksen. Sitä käytetään pysäyttämään suorittaminen kutsumalla clearInterval / clearTimeout .

    | | setInterval | setTimeout | || ----------- | ----------- | | Ajoitus | Puhelu on tiukasti ajastimella. Jos tulkki on varattu, yksi puhelu on jonossa. Toiminnon suoritusaikaa ei oteta huomioon, joten aikaväli yhden ajon lopusta toisen alkuun voi vaihdella. | Rekursiivista setTimeout-kutsua käytetään setIntervalin sijasta, jos suoritusten välillä tarvitaan kiinteä tauko. | | Viive | Minimiviive: 4ms. | Minimiviive: 4ms. | | Selaimen ominaisuudet | Latenssi 0 ei toimi IE:ssä | Operassa nollaviive vastaa 4 ms, ja muut viiveet käsitellään tarkasti, mukaan lukien epästandardit 1 ms, 2 ms ja 3 ms. |

    © 2024 ermake.ru - Tietoja PC-korjauksesta - Tietoportaali