„Javascript“ laikmačiai (setInterval, setTimeout). Apie tai, kaip veikia JavaScript laikmačiai Kartokite veiksmus nurodytu laiko intervalu javascript

Pradžia / Operacinės sistemos

„JavaScript“ skirtasis laikas yra vietinė „JavaScript“ funkcija, kuri paleidžia kodo dalį po nurodyto laiko delsos (milisekundėmis). Tai gali būti naudinga, kai jums reikia parodyti iššokantįjį langą, kai vartotojas praleido šiek tiek laiko jūsų puslapyje. O gal norite, kad užvedus pelės žymeklį virš elemento poveikis prasidėtų tik praėjus kuriam laikui? Tokiu būdu galite išvengti netyčinio efekto suaktyvinimo, jei vartotojas netyčia užvedė ant jo pelės žymeklį.

Paprastas setTimeout pavyzdys

Norėdami parodyti, kaip ši funkcija veikia, siūlau pažvelgti į šią demonstracinę versiją, kurioje praėjus dviem sekundėms po mygtuko paspaudimo pasirodo iššokantis langas.

Žiūrėti demonstraciją

Sintaksė

MDN dokumentacijoje pateikiama tokia setTimeout sintaksė:

var timeoutID = window.setTimeout(func, ); var timeoutID = window.setTimeout(kodas, );

  • timeoutID – skaitmeninis ID, kuris gali būti naudojamas kartu su clearTimeout() norint išjungti laikmatį;
  • func – funkcija, kurią reikia vykdyti;
  • kodas (alternatyvioje sintaksėje) – vykdomo kodo eilutė;
  • delsa – delsos trukmė milisekundėmis, po kurios funkcija bus paleista. Numatytoji reikšmė yra 0.
setTimeout vs window.setTimeout

Aukščiau pateikta sintaksė naudoja window.setTimeout . Kodėl?

Tiesą sakant, setTimeout ir window.setTimeout yra praktiškai ta pati funkcija. Vienintelis skirtumas yra tas, kad antroje išraiškoje mes naudojame setTimeout metodą kaip visuotinio lango objekto savybę.

Asmeniškai manau, kad tai tik daro kodą daug sudėtingesnį. Jei apibrėžtume alternatyvus metodas„JavaScript“ skirtasis laikas, kurį būtų galima rasti ir grąžinti pirmenybę, susidurtų su dar daugiau problemų.

Šiame vadove nenoriu blaškytis su lango objektu, bet apskritai jūs turite nuspręsti, kurią sintaksę naudoti.

Naudojimo pavyzdžiai

Tai gali būti funkcijos pavadinimas:

function explode())( alert("Boom!"); ) setTimeout(explode, 2000);

Kintamasis, nurodantis funkciją:

var explode = funkcija())( alert("Boom!"); ); setTimeout(sprogdinti, 2000);

Arba anoniminė funkcija:

setTimeout(function())( alert("Boom!"); ), 2000);

  • Toks kodas yra menkai suprantamas, todėl jį bus sunku modernizuoti ar derinti;
  • Tai apima eval() metodo naudojimą, kuris gali būti galimas pažeidžiamumas;
  • Šis metodas yra lėtesnis nei kiti, nes reikia paleisti JavaScript interpretatorių.

Taip pat atminkite, kad kodui išbandyti naudojame „JavaScript“ skirtojo laiko įspėjimo metodą.

Parametrų perdavimas į setTimout

Pirmojoje (ir kryžminėje naršyklėje) parinktyje perduodame parametrus atgalinio skambinimo funkcijai, vykdomai naudojant setTimeout.

Šiame pavyzdyje mes ištraukiame atsitiktinį sveikinimą iš sveikinimų masyvo ir perduodame jį kaip parametrą greet() funkcijai, kurią setTimeout vykdo su 1 sekundės delsa:

function greet(greeting)( console.log(greeting); ) function getRandom(arr)( return arr; ) var greetings = ["Sveiki", "Bonjour", "Guten Tag"], random Sveikinimai = getRandom(sveikinimai); setTimeout(function())( greet(atsitiktinis pasisveikinimas); ), 1000);

Žiūrėti demonstraciją

Alternatyvus metodas

Straipsnio pradžioje pateiktoje sintaksėje yra dar vienas būdas, kuriuo galite perduoti parametrus atgalinio skambinimo funkcijai, kurią vykdo „JavaScript“ laikas. Šis metodas reiškia visų parametrų išvestį po delsos.

Remdamiesi ankstesniu pavyzdžiu, gauname:

setTimeout(pasveikinimas, 1000, atsitiktinis pasisveikinimas);

Šis metodas neveiks IE 9 ir senesnėse versijose, kur perduoti parametrai traktuojami kaip neapibrėžti . Tačiau šiai problemai išspręsti yra specialus MDN polifilas.

Susijusios problemos ir „tai“

„setTimeout“ vykdomas kodas veikia atskirai nuo jį iškvietusios funkcijos. Dėl šios priežasties susiduriame su tam tikromis problemomis, kurias galima išspręsti naudojant šį raktinį žodį.

var person = ( vardas: "Jim", pristatymas: function())( console.log("Labas, aš"m " + this.firstName); ) ); person.introduce(); // Išvestys: Sveiki, aš " m Jim setTimeout(person.introduce, 50); // Išėjimai: Sveiki, aš neapibrėžtas

Šios išvesties priežastis yra ta, kad pirmame pavyzdyje tai nurodo asmens objektą, o antrame pavyzdyje nurodo visuotinio lango objektą, kuris neturi ypatybės firstName.

Norėdami atsikratyti šio neatitikimo, galite naudoti kelis metodus:

Priverskite tai nustatyti

Tai galima padaryti naudojant bind () metodą, kuris sukuria naują funkciją, kuri, iškvietus, naudoja konkrečią reikšmę kaip šio rakto reikšmę. Mūsų atveju nurodytas asmuo prieštarauja. Tai galiausiai mums suteikia:

setTimeout(person.introduce.bind(person), 50);

Pastaba: susiejimo metodas buvo įdiegtas ECMAScript 5, o tai reiškia, kad jis veiks tik naudojant šiuolaikinės naršyklės. Kitais atvejais, kai jį naudosite, gausite „JavaScript“ vykdymo klaidą „funkcijos skirtojo laiko klaida“.

Naudokite biblioteką

Daugelyje bibliotekų yra įmontuotų funkcijų, reikalingų šiai problemai išspręsti. Pavyzdžiui, jQuery.proxy() metodas. Ji paima funkciją ir grąžina naują, kuri visada naudos konkretų kontekstą. Mūsų atveju kontekstas bus toks:

setTimeout($.proxy(person.introduce, person), 50);

Žiūrėti demonstraciją

Laikmačio išjungimas

Grąžinama setTimeout reikšmė yra skaitmeninis ID, kurį galima naudoti norint išjungti laikmatį naudojant funkciją clearTimeout():

var laikmatis = setTimeout(myFunction, 3000); clearTimeout (laikmatis);

Pažiūrėkime tai veikiant. Toliau pateiktame pavyzdyje, jei spustelėsite mygtuką „Pradėti atgalinį skaičiavimą“, prasidės atgalinis skaičiavimas. Kai jis bus baigtas, kačiukai gaus savo. Bet jei spustelėsite mygtuką „Sustabdyti atgalinį skaičiavimą“, „JavaScript“ skirtojo laiko laikmatis bus sustabdytas ir nustatytas iš naujo.

Žiūrėti pavyzdį

Apibendrinkime

setTimeout yra asinchroninė funkcija, o tai reiškia, kad gautas šios funkcijos iškvietimas patenka į eilę ir bus vykdomas tik atlikus visus kitus krūvoje atliekamus veiksmus. Jis negali veikti kartu su kitomis funkcijomis arba atskira gija.

Metodas setInterval(), siūlomas „Window“ ir „Worker“ sąsajose, pakartotinai iškviečia funkciją arba vykdo kodo fragmentą su fiksuotu laiko tarpu tarp kiekvieno iškvietimo.

Jis grąžina intervalo ID, kuris unikaliai identifikuoja intervalą, todėl vėliau galėsite jį pašalinti iškviesdami clearInterval() . Šį metodą apibrėžia WindowOrWorkerGlobalScope maišytuvas. Sintaksė = var intervalID apimtis .setInterval(, func, [delsimas, arg1, ...]); Sintaksė = var intervalID apimtis arg2, func kodas ); Parameters func Funkcija, kuri turi būti vykdoma kas delsos milisekundes. Funkcijai nepateikiami jokie argumentai ir nesitikima grąžinti vertės. dėl tų pačių priežasčių, dėl kurių naudojant eval() kyla pavojus saugumui. .setInterval( uždelsimas Laikas milisekundėmis (tūkstančiomis sekundės dalimis), kurį laikmatis turi uždelsti tarp nurodytos funkcijos ar kodo vykdymo. Daugiau informacijos apie leistiną delsos verčių diapazoną rasite toliau.

arg1, ..., argN Neprivaloma Papildomi argumentai, kurie perduodami funkcijai, nurodytai pasibaigus laikmačiui. Pastaba: papildomų argumentų perdavimas setInterval() pirmoje sintaksėje neveikia

Internet Explorer

9 ir anksčiau. Jei norite įjungti šią funkciją toje naršyklėje, turite naudoti polifillą (žr. skyrių).

Grąžinimo vertė

Grąžintas intervalID yra skaitinė, ne nulis reikšmė, kuri identifikuoja laikmatį, sukurtą iškvietus setInterval() ; Šią reikšmę galima perduoti norint atšaukti skirtąjį laiką.

Gali būti naudinga žinoti, kad setInterval() ir setTimeout() turi tą patį ID telkinį ir kad clearInterval() ir clearTimeout() techniškai gali būti naudojami pakaitomis. Tačiau aiškumo dėlei turėtumėte stengtis visada juos suderinti, kad išvengtumėte painiavos tvarkant kodą.

Pastaba: delsos argumentas konvertuojamas į 32 bitų sveikąjį skaičių su ženklu. Tai veiksmingai apriboja delsą iki 2147483647 ms, nes IDL jis nurodytas kaip sveikasis skaičius.

Pavyzdžiai 1 pavyzdys: Pagrindinė sintaksė

Toliau pateiktame pavyzdyje parodyta pagrindinė setInterval() sintaksė.

Var intervalID = window.setInterval(myCallback, 500, "Parameter 1", "Parameter 2"); function myCallback(a, b) ( // Jūsų kodas čia // Parametrai yra visiškai neprivalomi. console.log(a); console.log(b); )

2 pavyzdys: dviejų spalvų kaitaliojimas

Toliau pateiktame pavyzdyje funkcija flashtext() iškviečiama kartą per sekundę, kol paspaudžiamas sustabdymo mygtukas.

setInterval/clearInterval pavyzdys var nIntervId;

function changeColor() ( nIntervId = setInterval(flashText, 1000); ) function flashText() ( var oElem = document.getElementById("mano_dėžutė"); oElem.style.color = oElem.style.color == "raudona" ? " mėlyna" : "raudona"; // oElem.style.color == "raudona" ? "mėlyna" : "raudona" yra trejopas operatorius. ) funkcija stopTextColor() ( clearInterval(nIntervId); )

Sveikas pasaulis

JavaScript rašomoji mašinėlė – MDN funkcijos Rašomosios mašinėlės pavyzdys (sSelector, nRate) ( funkcija švarus () ( clearInterval(nIntervId); bTyping = false; bStart = true; oCurrent = null; aSheets.length = nIdx = 0; ) funkcija slinkti (oSheet, nPossheet , bEraseAndStop) ( if (!oSheet.hasOwnProperty("parts") || 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; */ }

„Mozilla Developer Network“ „CopyLeft 2012“.

[ Žaisti | Pauzė | Nutraukti]

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 rašomoji mašinėlė

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:

Duis lobortis sapien quis nisl luctus porttitor. In tempor semper libero, eu tincidunt dolor eleifend sit amet. Ut niekur kitur velit in dolor tincidunt rhoncus non non diam. Morbi auctor ornare orci, non euismod felis gravida, niekur kitur nepriskirta. Curabitur elementum nisi a eros rutrum, niekur kitur 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, ir 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.

Atšaukimo argumentai

Kaip aptarta anksčiau, „Internet Explorer“ 9 ir senesnės versijos nepalaiko argumentų perdavimo atgalinio skambinimo funkcijai nei setTimeout() nei setInterval() . Šis specifinis IE kodas parodo būdą, kaip įveikti šį apribojimą. Norėdami naudoti, tiesiog pridėkite šį kodą scenarijaus viršuje.

/*\ |*| |*| IE būdingas daugialypis užpildymas, leidžiantis perduoti savavališkus argumentus į |*| „Javascript“ laikmačių atgalinio iškvietimo funkcijos (HTML5 standartinė sintaksė)..setInterval |*| https://site/User:fusionchess |*| |*| Sintaksė: |*| var timeoutID = window.setTimeout(funk, delay[, arg1, arg2, ...]); |*| var timeoutID = window.setTimeout(kodas, delsa); |*| var intervalID = langas.setInterval(funk, delsa[, arg1, arg2, ...]); |*| var intervalID = langas.setInterval(kodas, delsa); |*| \*/ if (document.all && !window.setTimeout.isPolyfill) ( var __nativeST__ = window.setTimeout; window.setTimeout = funkcija (vCallback, nDelay /*, argumentToPass1, argumentToPass2 ir kt. */) ( var aArgs = Masyvas .prototype.slice.call(argumentai, 2); return __nativeST__(vCallback instanceof Function () ( vCallback.apply(null, aArgs); ): vCallback, nDelay ); ( var __nativeSI__ = window.setInterval; window.setInterval = funkcija (vCallback, nDelay /*, argumentToPass1, argumentToPass2 ir kt. */) ( var aArgs = Array.prototype. slice.call(arguments, 2); return __nativeSI__(vCallback Funkcijos pavyzdys () ( vCallback.apply(null, aArgs); ): vCallback, nDelay );

Kita galimybė yra naudoti anoniminę funkciją, kad galėtumėte skambinti atgal, nors šis sprendimas yra šiek tiek brangesnis. Pavyzdys:

Var intervalID = setInterval(function() ( myFunc("vienas", "du", "trys"); ), 1000);

var intervalID = setInterval(function(arg1) ().bind(undefined, 10), 1000);

Neaktyviems skirtukams reikalinga „Gecko 5.0“ („Firefox 5.0“ / „Thunderbird 5.0“ / „SeaMonkey 2.2“)

Pradedant nuo „Gecko 5.0“ („Firefox 5.0“ / „Thunderbird 5.0“ / „SeaMonkey 2.2“), intervalai neaktyviuose skirtukuose suaktyvinami ne dažniau kaip kartą per sekundę.

"Šita" problema

Kai perduodate metodą setInterval() arba bet kuriai kitai funkcijai, jis iškviečiamas neteisingai nurodant šią reikšmę. Ši problema išsamiai paaiškinta „JavaScript“ nuorodoje.

Paaiškinimas

MyArray = ["nulis", "vienas", "du"]; myArray.myMethod = funkcija (sProperty) ( alert(arguments.length > 0 ? this : this); ); myArray.myMethod(); // spausdina "nulis, vienas, du" myArray.myMethod(1); // spausdina "one" setTimeout(myArray.myMethod, 1000); // atspausdina "" po 1 sekundės setTimeout(myArray.myMethod, 1500, "1"); // atspausdina "undefined" po 1,5 sek .myMethod // iš tikrųjų tai bus klaida, nes setTimeout kodas tikisi, kad tai bus lango objektas: setTimeout.call(myArray, myArray.myMethod, 2000); setTimeout.call(myArray, myArray.myMethod, 2500, 2) // ta pati klaida

Kaip matote, nėra būdų perduoti šį objektą atgalinio skambinimo funkcijai pasenusioje „JavaScript“.

Galimas sprendimas

Galimas būdas išspręsti šią problemą yra pakeisti dvi vietines setTimeout() arba setInterval() globalias funkcijas dviem. nevietiniai tie, kurie įgalina jų iškvietimą naudojant Function.prototype.call metodą. Toliau pateiktame pavyzdyje parodytas galimas pakeitimas:

// Įgalinkite „šio“ objekto perdavimą per „JavaScript“ laikmačius var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval; window.setTimeout = funkcija (vCallback, nDelay /*, argumentToPass1, argumentToPass2 ir kt. */) ( var oThis = tai, aArgs = Array.prototype.slice.call(arguments, 2); return __nativeST__(vCallback instanceof Function ? () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay ); window.setInterval = funkcija (vCallback, nDelay /*, argumentToPass1, argumentToPass2 ir kt. */) ( var oThis = tai, aArgs = Array.prototype.slice.call(arguments, 2); return __nativeSI__(vCallback instanceof Function ? () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay );

Šie du pakaitalai taip pat įgalina HTML5 standartinį savavališkų argumentų perdavimą į IE laikmačių atgalinio iškvietimo funkcijas. Taigi jie gali būti naudojami kaip neatitinka standartų polifilai taip pat. Žiūrėkite a atitinka standartus polifilas.

Naujos funkcijos testas:

MyArray = ["nulis", "vienas", "du"]; myArray.myMethod = funkcija (sProperty) ( alert(arguments.length > 0 ? this : this); ); setTimeout(alert, 1500, "Sveikas pasaulis!"); // išsaugomas standartinis setTimeout ir setInterval naudojimas, bet... setTimeout.call(myArray, myArray.myMethod, 2000); // atspausdina "zero,one,du" po 2 sekundžių setTimeout.call(myArray, myArray.myMethod, 2500, 2); // išspausdina "du" po 2,5 sekundės

Sudėtingesnei, bet vis tiek modulinei jos versijai ( Demonas) žr. JavaScript demonų valdymą. Ši sudėtingesnė versija yra ne kas kita, kaip didelis ir keičiamo dydžio metodų rinkinys Demonas konstruktorius. Tačiau, Demonas pats konstruktorius yra ne kas kita, kaip klonas MiniDaemon su papildoma parama init ir pradžios funkcijos, deklaruotos egzistavimo metu demonas. Taigi, MiniDaemon sistema išlieka rekomenduojamas paprastas animacijos būdas, nes Demonas be jos metodų rinkinio iš esmės yra jos klonas.

minidaemon.js /*\ |*| |*| :: MiniDaemon:: |*| |*| 2 peržiūra – 2014 m. rugsėjo 26 d.setInterval |*| https://site/User:fusionchess |*| https://github.com/madmurphy/minidaemon.js |*| |*| Ši sistema yra išleista pagal GNU Lesser General Public License, 3 arba naujesnę versiją. |*| http://www.gnu.org/licenses/lgpl-3.0.html |*| \*/ funkcija MiniDaemon (oOwner, fTask, nRate, nLen) ( if (!(this && this MiniDaemon egzempliorius)) ( 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 = Begalybė;< 1: this.INDEX + 1 >tai.ilgis; ); MiniDaemon.prototype.synchronize = funkcija () ( if (this.PAUSED) ( return; ) clearInterval(this.SESSION); this.SESSION = setInterval(MiniDaemon.forceCall, this.rate, this); ); MiniDaemon.prototype.pause = funkcija () ( clearInterval(this.SESSION); this.PAUSED = true; ); MiniDaemon.prototype.start = funkcija (bReverse) ( var bBackw = Būlio (bReverse); if (this.BACKW === bBackw && (this.isAtEnd() || !this.PAUSED)) ( return; ) this.BACKW = bBackw; tai.PAUSED = false this.synchronize();

MiniDaemon perduoda argumentus atgalinio skambinimo funkcijai. Jei norite dirbti su naršyklėmis, kurios iš esmės nepalaiko šios funkcijos, naudokite vieną iš anksčiau pasiūlytų metodų.

Sintaksė

var myDaemon = new MiniDaemon( šis objektas, atgalinis skambutis[ , norma [, ilgio]]);

Aprašymas Naudojimo pastabos

Funkcija setInterval() dažniausiai naudojama norint nustatyti vėl ir vėl vykdomų funkcijų, pvz., animacijų, delsą. Intervalą galite atšaukti naudodami WindowOrWorkerGlobalScope.clearInterval() .

Jei norite, kad jūsų funkcija būtų iškviesta vieną kartą po nurodyto vėlavimo naudokite .

Vėlavimo apribojimai

Galima įterpti intervalus; tai yra, setInterval() atgalinis skambutis gali iškviesti setInterval(), kad būtų paleistas kitas intervalas, net jei pirmasis vis dar vyksta. Siekiant sumažinti galimą poveikį, kurį tai gali turėti našumą, kai intervalai įterpiami daugiau nei penkių lygių gylyje, naršyklė automatiškai taikys mažiausią 4 ms vertę.

Tam tikromis aplinkybėmis naršyklės gali taikyti dar griežtesnes minimalias intervalo vertes, nors tai neturėtų būti įprasta. Taip pat atkreipkite dėmesį, kad tikrasis laikas, praeinantis tarp skambučių į atgalinį ryšį, gali būti ilgesnis nei nurodyta delsa; pavyzdžius žr. Priežastys, dėl kurių vėluojama ilgiau nei nurodyta WindowOrWorkerGlobalScope.setTimeout().

Įsitikinkite, kad vykdymo trukmė yra trumpesnė nei intervalo dažnis

Jei yra tikimybė, kad logikos vykdymas gali užtrukti ilgiau nei intervalo laikas, rekomenduojama rekursyviai iškviesti pavadintą funkciją naudojant setTimeout() . Pavyzdžiui, jei nuotolinio serverio apklausai kas 5 sekundes naudojate setInterval(), tinklo delsa, nereaguojantis serveris ir daugybė kitų problemų gali neleisti užklausai įvykdyti per numatytą laiką. Todėl galite susidurti su XHR užklausomis, kurios nebūtinai grįš tvarkingai.

Labai svarbu suprasti, kaip veikia JavaScript laikmačiai. Dažnai jų elgesys nesutampa su mūsų intuityviu supratimu apie daugiagiją, ir taip yra dėl to, kad iš tikrųjų jie vykdomi vienoje gijoje. Pažvelkime į keturias funkcijas, kuriomis galime valdyti laikmačius:

  • var id = setTimeout(fn, delsa); - Sukuria paprastą laikmatį, kuris iškvies tam tikrą funkciją po tam tikro delsos. Funkcija grąžina unikalų ID, su kuriuo galima pristabdyti laikmatį.
  • var id = setInterval(fn, delsa); - Panašus į setTimeout, bet nuolat iškviečia funkciją tam tikru intervalu (iki sustabdymo).
  • clearInterval(id);, clearTimeout(id); - Priima laikmačio ID (grąžina viena iš aukščiau aprašytų funkcijų) ir sustabdo atgalinio skambinimo vykdymą"a.
Pagrindinė mintis, į kurią reikia atsižvelgti, yra ta, kad laikmačio delsos laikotarpio tikslumas nėra garantuotas. Pirmiausia naršyklė vykdo visus asinchroninius „JavaScript“ įvykius vienoje gijoje (pvz., pelės paspaudimus ar laikmačius) ir tik tuo metu, kai ateina to įvykio eilė. Tai geriausiai parodo ši diagrama:

Šiame paveiksle yra gana daug informacijos, tačiau ją supratę galėsite geriau suprasti, kaip veikia „JavaScript“ asinchronija. Ši diagrama rodo laiką vertikaliai milisekundėmis, mėlyni blokai rodo įvykdytus JavaScript kodo blokus. Pavyzdžiui, pirmasis blokas vidutiniškai įvykdomas per 18 ms, pelės paspaudimas blokuoja vykdymą maždaug 11 ms ir t.

„JavaScript“ gali vykdyti tik vieną kodo dalį (dėl vienos gijos vykdymo pobūdžio), kurių kiekvienas blokuoja kitų asinchroninių įvykių vykdymą. Tai reiškia, kad kai įvyksta asinchroninis įvykis (pvz., pelės paspaudimas, laikmačio iškvietimas arba XMLHttp užklausos užbaigimas), jis įtraukiamas į eilę ir vykdomas vėliau (įdiegimas, žinoma, skiriasi priklausomai nuo naršyklės, bet susitarkime vadinkite tai „eile“).

Pirmiausia įsivaizduokime, kad „JavaScript“ bloke paleidžiami du laikmačiai: setTimeout su 10 ms vėlavimu ir setInterval su tuo pačiu vėlavimu. Priklausomai nuo to, kada įsijungs laikmatis, jis įsijungs tuo metu, kai dar neužbaigsime pirmojo kodo bloko. Tačiau atkreipkite dėmesį, kad jis neužsidega iš karto (tai neįmanoma dėl vieno sriegio). Vietoj to, atidėta funkcija įtraukiama į eilę ir vykdoma kitą galimą momentą.

Be to, vykdant pirmąjį „JavaScript“ bloką, įvyksta pelės paspaudimas. Šio asinchroninio įvykio (ir jis yra asinchroninis, nes negalime jo numatyti) tvarkyklės šiuo metu negali būti vykdomos iš karto, todėl jis taip pat patenka į eilę, kaip ir laikmatis.

Įvykdžius pirmąjį JavaScript kodo bloką, naršyklė užduoda klausimą: „Kas laukia, kol bus įvykdytas? IN šiuo atveju Pelės paspaudimo tvarkyklė ir laikmatis yra laukiančios būsenos. Naršyklė pasirenka vieną iš jų (paspaudimų tvarkyklę) ir jį vykdo. Laikmatis lauks kitos galimos laiko dalies vykdymo eilėje.

Atminkite, kad vykdant pelės paspaudimų tvarkyklę suaktyvinamas pirmasis intervalinis atgalinis iškvietimas. Kaip ir laikmatis-atskambinimas, jis bus eilėje. Tačiau atminkite, kad vėl suaktyvinus intervalą (kai veikia laikmatis-atskambinimas), jis bus pašalintas iš eilės. Jei visi intervaliniai atgaliniai iškvietimai būtų įrašyti į eilę, kai vykdoma didelė kodo dalis, lauktų daugybė funkcijų, kurių vykdymas nebus atidėtas liko eilėje, prieš įtraukdami į eilę kitą.

Taigi galime stebėti atvejį, kai trečiasis intervalo-atšaukimo paleidimas sutampa su momentu, kai jis jau įvykdomas. Tai iliustruoja svarbų dalyką: intervalams nesvarbu, kas šiuo metu veikia, jie bus įtraukti į eilę neatsižvelgiant į vėlavimo laikotarpį tarp vykdymų.

Galiausiai, kai baigsis antrasis intervalinis atgalinis skambutis, pamatysime, kad „JavaScript“ varikliui nebelieka nieko vykdyti. Tai reiškia, kad naršyklė vėl laukia naujų asinchroninių įvykių. Tai įvyks ties 50 ms žyma, kai vėl veiks intervalinis atgalinis skambutis. Šiuo metu nebus nieko, kas jį blokuotų, todėl jis veiks nedelsiant.

Pažvelkime į pavyzdį, kuris puikiai iliustruoja skirtumą tarp setTimeout ir setInterval.
setTimeout(function())( /* Kažkoks ilgas kodo blokas... */ setTimeout(arguments.callee, 10); ), 10);
Šie du variantai iš pirmo žvilgsnio yra lygiaverčiai, tačiau iš tikrųjų taip nėra. Kodas naudojant setTimeout visada turės mažiausiai 10 ms delsą po ankstesnio skambučio (gali būti daugiau, bet niekada mažiau), o kodas naudojant setInterval bus linkęs iškviesti kas 10 ms, neatsižvelgiant į tai, kada įvyko ankstesnis skambutis.

Apibendrinkime viską, kas pasakyta aukščiau:
- „JavaScript“ varikliai naudoja vienos gijos aplinką, konvertuodami asinchroninius įvykius į eilę, laukiančią vykdymo,
- Funkcijos setTimeout ir setInterval asinchroniniame kode vykdomos iš esmės skirtingai,
- Jei laikmačio negalima įjungti šiuo metu, jis bus atidėtas iki kito vykdymo taško (kuris bus ilgesnis nei pageidaujamas vėlavimas),
- Intervalai (setInterval) gali būti vykdomi vienas po kito be uždelsimo, jei jų vykdymas užtrunka ilgiau nei nurodyta delsa.

Visa tai nepaprastai svarbi informacija plėtrai. Žinant, kaip veikia „JavaScript“ variklis, ypač esant daugybei asinchroninių įvykių (kas dažnai nutinka), yra puikus pagrindas kurti pažangias programas.

Programuojant skriptų kalbomis, periodiškai reikia sukurti pauzę – kuriam laikui pristabdyti programos vykdymą, o tada tęsti darbą. Pavyzdžiui, VBS ir PHP scenarijuose galimi šie metodai:

VBS: wscript.sleep 1500 (sustabdykite 1,5 sekundės)

PHP: miegas (10); (sustabdyti 10 sekundžių)

Tokių pauzių metu vykdymo sistema (PHP arba VBS) nieko nedaro. Kūrėjas, bandantis intuityviai naudoti kažką panašaus „Javascript“, bus nemaloniai nustebintas. Įprasta klaida bandant sukurti pauzę „Javascript“ atrodo taip:

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

Manote, kad kai ciklo metu ateis eilė brėžti kitą skaičių, jūsų setTimeout sąžiningai sustabdys Javascript veikimą, palaukite 0,9 sekundės, įvesties lauko gale pridės norimą skaičių ir tęs darbą. Tačiau iš tikrųjų taip nėra: setInterval ir setTimeout Javascript tik atideda skliausteliuose nurodyto veiksmo (arba funkcijos) vykdymą. Mūsų pavyzdyje atsitiks taip:

  • i = 1;
  • atidėti 0,9 sekundės skaičiaus „1“ įtraukimą į įvesties lauką;
  • Iš karto po šios problemos nustatymo ciklas tęsiasi: i=2;
  • atidėti 0,9 sekundės skaičiaus „2“ įtraukimą į įvesties lauką;
  • Iškart reiškia, pavyzdžiui, 1 ms (tai yra neproporcingai maža, palyginti su 900 ms): ciklas atliks savo darbą beveik akimirksniu, sukurdamas kelias atidėtas užduotis iš to paties momento. Tai reiškia, kad visos laukiančios „piešimo“ užduotys bus baigtos beveik tuo pačiu metu, be pertraukų tarp naujų skaičių pridėjimo. Prasideda ciklas; viskas užšąla 0,9 s; ir shirr – visi skaičiai šaudomi iš eilės vienas po kito.

    Kaip tokiu atveju teisingai pritaikyti setTimeout? Tai sudėtinga. Turėsite iškviesti funkciją rekursyviai(iš funkcijos ta pati funkcija) ir kad šis procesas nebūtų begalinis, nustatykite sustabdymo sąlygą (pvz., spausdinamo numerio dydį):

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

    Ir kintamasis i turės būti inicijuotas už funkcijos ribų, pavyzdžiui, taip:

    Dabar viskas veikia kaip priklauso (uždelsimo laiką sumažinome nuo 0,9 s iki 0,4 s). Tačiau tokioms užduotims logiškiau naudoti setInterval, o ne setTimeout (nors tam reikės dviejų funkcijų):

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

    Javascirpt setInterval metodo ypatumas yra tas, kad jis nepraeina „savaime“ jį reikia sustabdyti specialiu clearInterval metodu. O kad būtų aišku, ką tiksliai sustabdyti, užduočiai atidėtam veiksmui priskiriamas specialus identifikatorius – laikmatis: window.timer1 = window.setInterval(...) .

    Identifikatorius taip pat galima priskirti užduotims, sukurtoms setTimeout metodu. Visi laikmačio ID turi skirtis vienas nuo kito (unikalus esamame naršyklės lange). Tada lange galite sukurti keletą skirtingų užduočių, kurios naudoja atidėtus veiksmus, ir šios užduotys bus vykdomos lygiagrečiai (kaip vienu metu, jei kompiuteryje yra pakankamai resursų), o tai iš esmės neįmanoma PHP ar VBS.

    Štai puslapio, kuriame vienu metu veikia keli „Javascript“ laikmačiai, pavyzdys: setinterval.htm (Javascript funkcijos rinkmenoje setinterval.js). Visus puslapių laikmačius (išskyrus meniu) galima sustabdyti naudojant Esc klavišą. Visi laikmačių pavyzdžiai yra pagrįsti „natūraliu“ (o ne abstrakčiu i++) atgaline atskaita – laiku arba atstumu. Visi „laikrodžiai“ yra specialiai desinchronizuoti (aiškumo dėlei). Nuo atstumo priklausomi laikmačiai naudojami „indikatoriuje“ ir išskleidžiamajame („ištraukiamas“) meniu.

    Išskleidžiamasis meniu

    Mūsų stumdomas meniu iš tikrųjų yra slenkantis (iš po „antraštės“): tarp elementų yra specialiai palikti tarpai, kad matytumėte, kaip jis išslysta. Netikėtai paaiškėjo, kad skirtingo ilgio sąrašams išėjimo nepavyko padaryti vienodai sklandaus – tikriausiai dėl mažo kompiuterio našumo (AMD Athlon 999 MHz).

    Visiškai akivaizdu, kad grožiui ir harmonijai būtina, kad skirtingų meniu punktų sąrašai atsirastų vienu metu. Tai reiškia, kad ilgesni sąrašai turėtų iškristi su daugiau didelis greitis, trumpesni - mažesniu greičiu. Atrodytų, kad tai būtų galima įgyvendinti taip:

  • Pavyzdžiui, nustatome bendrą „išvykimo“ laiką iki 200 ms.
  • Jei išskleidžiamojo sąrašo aukštis yra 20 px, akivaizdu, kad galime jį perkelti vienu pikseliu žemyn per 10 ms intervalą – tada po 200 ms išeis visas sąrašas.
  • Jei išskleidžiamasis meniu yra 40 pikselių aukščio, kad tilptų į tiek pat laiko, turime jį perkelti vienu pikseliu žemyn kas 5 ms.
  • Pagal šią logiką, jei išskleidžiamasis sąrašas yra 200 pikselių aukščio, turėtume jį perkelti vienu pikseliu žemyn kas 1 ms. Bet toks greitis mūsų kompiuteryje neveikia – naršyklė tiesiog nespėja per vieną milisekundę nupiešti naujos sąrašo padėties. Taip. Javascript sugeba suskaičiuoti (ką čia skaičiuoti?), bet naršyklė (Firefox) neturi laiko rodyti. Tipiška žiniatinklio situacija.

    Todėl daugiau ar mažiau suvienodinti meniu išvykimo laiką galima tik ramentų pagalba, o kaip tai veiks daugiau, kol kas neaišku greitas kompiuteris. Bet turėtume pasikliauti lėčiausiu, tiesa? Algoritmas (neatsižvelgiant į kompiuterio greitį) pasirodo maždaug toks:

  • Nustatykite bendrą sąrašo tikrinimo laiką: laikas = 224 (ms).
  • Nustatome minimalų vieno intervalo laiką cikle: delsa = 3 (ms).
  • Nustatykite mažiausią sąrašo perkėlimo žingsnį: poslinkis = 1 (px).
  • Visa tai keičiame priklausomai nuo sąrašo aukščio: 1) padidiname vėlavimo (intervalo) laiką atvirkščiai proporcingai aukščiui ir tiesiogiai proporcingai bendram laiko laikui (224 aukštyje koeficientas yra 1); 2) jei aukštis didesnis nei 40 px, proporcingai ūgiui padidinti minimalų žingsnį. Konstanta „40“ buvo gauta eksperimentiniu būdu lėčiausiam kompiuteriui. Testai Pentium 4 CPU 2,53GHz kompiuteriu atskleidė lygiai tokį patį skaičių – 40. Priešingu atveju laikmačiai išeina iš rikiuotės, sąrašai neveikia.
  • Dabar sąrašai daugiau ar mažiau pasirodo. Daugiau ar mažiau panašiam laikui. Puslapyje setinterval.htm.

    Ir štai Bruce'as:

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

    Pati funkcija, kuri išstumia įdėtus sąrašus iš meniu, kaip matome, yra labai paprasta. Belieka jį paleisti naudojant kažką panašaus į šią eilutę:

    Ts.timer1 = setInterval(function())(slide_do(ts, maxtop, offset)), delsa)

    Na, prieš pradėdami, tiesiog apskaičiuokite visus šiuos maxtop ir poslinkius, taip pat įtraukite sąrašą į mintop poziciją. Štai ką daro 40 eilučių „preliminari“ skaidrė () funkcija. Ir viskas kartu – faile setinterval.js. Taip, ir šis šūdas visai neveiks be įtraukto stilių failo

    • Iš:
    • Registruota: 2014-07-08
    • Žinutės: 3 896
    • Patinka: 497
    Tema: „SetTimeOut“ ir „SetInterval“, kurią geriau naudoti „JavaScript“?

    Funkcija setInterval skirta paleisti kodą kelis kartus reguliariais intervalais. Tačiau jis turi daug trūkumų, daugiausia skirtingą elgesį skirtingos naršyklės.

    Pirmasis skirtumas yra laiko, kai laikmatis nustatomas kitam paleidimui, skirtumas. Sukurkime nedidelį testą: išmatuosime, kiek laiko praėjo nuo ankstesnio važiavimo pradžios ir nuo jo pabaigos.

    var d1 = new Data(), d2 = new Data(); setInterval(function() ( var d = new Data(); document.body.innerHTML += (d - d1) + " " + (d - d2) + "
    "; // Pažymėkite funkcijos d1 = new Date(); while (new Date() - d1< 200); // ничего не делаем 200 миллисекунд // И в конце функции d2 = new Date(); }, 1000);

    Išvestis bus informatyvi, pradedant nuo antros eilutės.

    „Firefox“, „Opera“, „Safari“ ir „Chrome“ situacija bus panaši: pirmasis skaičius bus maždaug lygus 1000, antrasis - 200 mažiau. Skirsis tik vertybių sklaida. Mažiausias skirtumas yra „Chrome“ ir „Opera“.

    2 PunBB atsakymas (redagavo PunBB 2017.06.08 16:45)
    • Iš: Maskva, Sovkhoznay 3, apt. 98
    • Registruota: 2014-07-08
    • Žinutės: 3 896
    • Patinka: 497

    Kitas mažiau pastebimas ir sunkiau atgaminamas, bet kartais galintis sukelti daug rūpesčių skirtumas – atsparumas sistemos laiko pokyčiams. Jei atliksite toliau pateiktą testą

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

    Ir po paleidimo nustatykite sistemos laiką minute atgal, tada į Firefox naršyklės ir Safari, numerio keitimas bus pristabdytas, o po minutės prasidės iš naujo. Žinoma, rankinis sistemos laiko vertimas yra itin reta situacija, tačiau daugelis sistemų yra sukonfigūruotos automatiškai sinchronizuoti laiką su serveriais internete, todėl kai kuriose situacijose šio faktoriaus negalima atmesti.

    Kitas nedidelis setInterval funkcijos trūkumas yra tas, kad norint sustabdyti jos veikimą, reikia kažkur atsiminti jos identifikatorių, o tai ne visada patogu.

    3 PunBB atsakymas
    • Iš: Maskva, Sovkhoznay 3, apt. 98
    • Registruota: 2014-07-08
    • Žinutės: 3 896
    • Patinka: 497
    Re: „SetTimeOut“ ir „SetInterval“, kurį geriau naudoti „JavaScript“?

    Norėdami atsikratyti išvardytų setInterval trūkumų, galite naudoti kelis setTimeout.

    Svarbi setInterval alternatyva yra rekursinis setTimeout:

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

    Aukščiau pateiktame kode kitas vykdymas suplanuojamas iškart po to, kai baigiasi ankstesnis.

    Rekursyvus setTimeout yra lankstesnis laiko nustatymo metodas nei setInterval, nes laikas iki kito vykdymo gali būti suplanuotas skirtingai, atsižvelgiant į dabartinio vykdymo rezultatus.

    Pavyzdžiui, turime paslaugą, kuri kas 5 sekundes apklausia serverio naujų duomenų. Jei serveris yra perkrautas, galite padidinti apklausų intervalą iki 10, 20, 60 sekundžių... Ir tada grąžinti jį atgal, kai viskas grįš į normalias vėžes.

    Jei reguliariai vykdome daug procesoriaus reikalaujančias užduotis, galime įvertinti jų vykdymo laiką ir planuoti kitą paleidimą anksčiau ar vėliau.

    4 PunBB atsakymas
    • Iš: Maskva, Sovkhoznay 3, apt. 98
    • Registruota: 2014-07-08
    • Žinutės: 3 896
    • Patinka: 497
    Re: „SetTimeOut“ ir „SetInterval“, kurį geriau naudoti „JavaScript“?

    Rekursyvus setTimeout garantuoja pauzę tarp skambučių, setInterval – ne.

    Palyginkime du kodus. Pirmasis naudoja setInterval:

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

    Antrasis naudoja rekursyvų setTimeout:

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

    Naudojant setInterval, vidinis laikmatis įsijungs tiksliai kas 100 ms ir iškvies func(i):

    Tikroji pauzė tarp func skambučių su setInterval yra mažesnė nei nurodyta kode!

    Tai natūralu, nes niekaip neatsižvelgiama į funkcijos veikimo laiką, ji „suvalgo“ dalį intervalo.

    Taip pat gali būti, kad funkcija pasirodė sudėtingesnė nei tikėjomės ir užtruko ilgiau nei 100 ms.

    Tokiu atveju vertėjas lauks, kol funkcija bus baigta, tada patikrins laikmatį ir, jei jau atėjo (arba praėjo) iškvietimo setInterval laikas, iš karto įvyks kitas skambutis.

    Jei funkcija veikia ilgiau nei setInterval pauzė, skambučiai vyks be jokių trikdžių.

    5 Atsakyti sempai
    • Iš: Jeruzalė
    • Registruota: 2015-06-02
    • Žinutės: 958
    • Patinka: 274
    Re: „SetTimeOut“ ir „SetInterval“, kurį geriau naudoti „JavaScript“?

    Viskas priklauso nuo atliekamos užduoties. Iš pradžių SetTimeOut naudojamas vieną kartą paleisti laikmatį, o SetInterval naudojamas ciklas paleisti. Tačiau abi funkcijos gali būti naudojamos scenarijus paleisti cikliškai, jei, pavyzdžiui, paleidžiate juos rekursyviai SetTimeOut funkcijos, tada jis veiks beveik identiškai SetInterval.

    „SetInterval“ minusas šiuo metu yra tas, kad neatsižvelgiama į paties scenarijaus (funkcijos) vykdymo laiką, o jei, pavyzdžiui, naudosite jį sunkioms užklausoms, tada intervalo laikas žymiai sumažės, o skirtingose ​​naršyklėse gali skirtis.

    Tačiau vėlgi, jei funkcija ar užklausa yra sumažinta, galutinis vartotojas vargu ar pajus skirtumą.
    Todėl ką naudoti, kiekvienas sprendžia pats.

    © 2024 ermake.ru - Apie kompiuterių taisymą - Informacinis portalas