Repetați acțiunile la un interval de timp javascript specificat. Exemple ale funcției jQuery setTimeout()

Acasă / Tehnologii

Metoda setInterval(), oferită pe interfețele Window și Worker, apelează în mod repetat o funcție sau execută un fragment de cod, cu o întârziere fixă ​​între fiecare apel.

Returnează un ID de interval care identifică în mod unic intervalul, astfel încât să îl puteți elimina mai târziu apelând clearInterval() . Această metodă este definită de mixin-ul WindowOrWorkerGlobalScope. Sintaxă = var intervalID domeniul de aplicare .setInterval(, func, [întârziere, arg1, ...]); Sintaxă = var intervalID domeniul de aplicare arg2, func cod ); Parametri func O funcție care trebuie executată la fiecare întârziere în milisecunde. Funcției nu i se transmite niciun argument și nu se așteaptă nicio valoare returnată. cod O sintaxă opțională vă permite să includeți un șir în loc de o funcție, care este compilată și executată la fiecare milisecunde de întârziere. Această sintaxă este .setInterval( nerecomandat

din aceleași motive care fac din utilizarea eval() un risc de securitate. delay Timpul, în milisecunde (mii de secundă), temporizatorul ar trebui să întârzie între execuțiile funcției sau codului specificat. Vedeți mai jos pentru detalii despre intervalul permis de valori de întârziere. arg1, ..., argN Opțional Argumente suplimentare care sunt transmise funcției specificate de

odată ce cronometrul expiră.

Notă: trecerea de argumente suplimentare setInterval() în prima sintaxă nu funcționează

Internet Explorer

9 și mai devreme. Dacă doriți să activați această funcționalitate pe acel browser, trebuie să utilizați o completare polivalentă (vezi secțiunea).

Valoarea returnată

IntervalID returnat este o valoare numerică, diferită de zero, care identifică temporizatorul creat de apelul la setInterval() ; această valoare poate fi transmisă pentru a anula timeout-ul.

Var intervalID = window.setInterval(myCallback, 500, „Parametrul 1”, „Parametrul 2”); function myCallback(a, b) ( // Codul dvs. aici // Parametrii sunt pur optionali. console.log(a); console.log(b); )

Exemplul 2: Alternarea a două culori

Următorul exemplu apelează funcția flashtext() o dată pe secundă până când este apăsat butonul Stop.

exemplu setInterval/clearInterval var nIntervId;

function changeColor() ( nIntervId = setInterval(flashText, 1000); ) function flashText() ( var oElem = document.getElementById("my_box"); oElem.style.color = oElem.style.color == "rosu" ? " albastru": "roșu"; // oElem.style.color == "roșu" ? "albastru": "roșu" este un operator ternar. ) funcția stopTextColor() ( clearInterval(nIntervId); )

Salut Lume

Stop

Exemplul 3: Simularea mașinii de scris

Următorul exemplu simulează mașina de scris prin ștergerea întâi și apoi tastând încet conținutul în NodeList care se potrivește cu un anumit grup de selectori.< 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 Machinewriter - MDN Exemplu de funcție Typewriter (sSelector, nRate) ( function clean () ( clearInterval(nIntervId); bTyping = false; bStart = true; oCurrent = null; aSheets.length = nIdx = 0; ) function scroll (oSheet, nPos , bEraseAndStop) ( dacă (!oSheet.hasOwnProperty(„parts”) || aMap.length

CopyLeft 2012 de la Mozilla Developer Network

[ Joacă | Pauză | Terminați]

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.

Mașină de scris JavaScript
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 torttor 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 torttor. 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 facilitati. 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 torttor ultricies ac. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec libero nunc. Nullam torttor nunc, elementum a consectetur et, ultrices eu orci. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a nisl eu sem vehicula egestas.

Argumente de apel invers

După cum sa discutat anterior, versiunile Internet Explorer 9 și mai jos nu acceptă transmiterea de argumente către funcția de apel invers nici în setTimeout() sau setInterval() . Următorul cod specific IE demonstrează o metodă pentru a depăși această limitare. Pentru a utiliza, pur și simplu adăugați următorul cod în partea de sus a scriptului.

/*\ |*| |*| Polyfill specific IE care permite trecerea de argumente arbitrare la |*| funcțiile de apel invers ale temporizatoarelor javascript (sintaxă standard HTML5)..setInterval |*| https://site/Utilizator:fusionchess |*| |*| Sintaxă: |*| var timeoutID = window.setTimeout(func, delay[, arg1, arg2, ...]); |*| var timeoutID = window.setTimeout(cod, întârziere); |*| var intervalID = window.setInterval(func, delay[, arg1, arg2, ...]); |*| var intervalID = window.setInterval(cod, întârziere); |*| \*/ dacă (document.all && !window.setTimeout.isPolyfill) ( var __nativeST__ = window.setTimeout; window.setTimeout = funcție (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) ( var aArgs = Array .prototype.slice.call(argumente, 2); return __nativeST__(vCallback instanceof Function () (vCallback.apply(null, aArgs); ): vCallback, nDelay if (document.all && !window.setInterval.isPolyfill); ( var __nativeSI__ = window.setInterval; window.setInterval = funcție (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) ( var aArgs = Array.prototype. slice.call(arguments, 2); return __nativeSI__(vCallback) instanceof Funcție () ( vCallback.apply(null, aArgs); ): vCallback, nDelay );

O altă posibilitate este să utilizați o funcție anonimă pentru a vă apela înapoi, deși această soluție este puțin mai scumpă. Exemplu:

Var intervalID = setInterval(function() ( myFunc("unu", "doua", "trei"); ), 1000);

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

File inactive Necesită Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)

Începând cu Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2), intervalele sunt fixate pentru a se declanșa nu mai des de o dată pe secundă în filele inactive.

Problema "aceasta".

Când treceți o metodă setInterval() sau orice altă funcție, aceasta este invocată cu această valoare greșită. Această problemă este explicată în detaliu în referința JavaScript.

Explicaţie

MyArray = ["zero", "unu", "două"]; myArray.myMethod = function (sProperty) ( alert(arguments.length > 0 ? this : this); ); myArray.myMethod(); // afișează „zero,unu,dou” myArray.myMethod(1); // afișează „one” setTimeout(myArray.myMethod, 1000); // afișează „” după 1 secundă setTimeout(myArray.myMethod, 1500, „1”); // se afișează „nedefinit” după 1,5 secunde // trecerea obiectului „acest” cu .call nu va funcționa // deoarece acest lucru va schimba valoarea acestui însuși setTimeout // în timp ce dorim să schimbăm valoarea acestuia în myArray .myMethod // de fapt, va fi o eroare deoarece codul setTimeout se așteaptă ca acesta să fie obiectul fereastră: setTimeout.call(myArray, myArray.myMethod, 2000 // eroare: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Operație ilegală pe obiectul prototip WrappedNative"); setTimeout.call(myArray, myArray.myMethod, 2500, 2);

După cum puteți vedea, nu există modalități de a trece acest obiect la funcția de apel invers în JavaScript moștenit.

O posibila solutie

O posibilă modalitate de a rezolva problema „această” este înlocuirea celor două funcții globale setTimeout() sau setInterval() native cu două non-nativ cele care permit invocarea lor prin metoda Function.prototype.call. Următorul exemplu arată o posibilă înlocuire:

// Activează trecerea obiectului „acest” prin temporizatoarele JavaScript var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval; window.setTimeout = funcție (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) ( var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2); return __nativeST__(vCallback instanceof Function ? () ( vCallback.apply(oThis, aArgs); ): vCallback, nDelay ); window.setInterval = funcție (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) ( var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2); return __nativeSI__(vCallback instanceof Function ? () ( vCallback.apply(oThis, aArgs); ): vCallback, nDelay );

Aceste două înlocuiri permit, de asemenea, trecerea standard HTML5 a argumentelor arbitrare la funcțiile de apel invers ale temporizatoarelor din IE. Deci pot fi folosite ca neconforme cu standardele de asemenea poliumpluturi. Vezi pentru a conform cu standardele poliumplutură.

Test de caracteristici noi:

MyArray = ["zero", "unu", "două"]; myArray.myMethod = function (sProperty) ( alert(arguments.length > 0 ? this : this); ); setTimeout(alertă, 1500, „Bună lume!”); // se păstrează utilizarea standard a setTimeout și setInterval, dar... setTimeout.call(myArray, myArray.myMethod, 2000); // afișează „zero,one,two” după 2 secunde setTimeout.call(myArray, myArray.myMethod, 2500, 2); // afișează „două” după 2,5 secunde

Pentru o versiune mai complexă, dar totuși modulară a acesteia ( Daemon) vezi Managementul demonilor JavaScript. Această versiune mai complexă nu este altceva decât o colecție mare și scalabilă de metode pentru Daemon constructor. Cu toate acestea, cel Daemon constructorul în sine nu este altceva decât o clonă a MiniDaemon cu un suport suplimentar pentru initşi la pornire funcţii declarate în timpul instanţierii demonul. Deci MiniDaemon framework rămâne modalitatea recomandată pentru animațiile simple, deoarece Daemon fără colecția sa de metode este în esență o clonă a acesteia.

minidaemon.js /*\ |*| |*| :: MiniDaemon:: |*| |*| Revizia #2 - 26 septembrie 2014.setInterval |*| https://site/Utilizator:fusionchess |*| https://github.com/madmurphy/minidaemon.js |*| |*| Acest cadru este lansat sub Licența Publică Generală Inferioară GNU, versiunea 3 sau mai recentă. |*| http://www.gnu.org/licenses/lgpl-3.0.html |*| \*/ funcția MiniDaemon (oOwner, fTask, nRate, nLen) ( if (!(aceasta și& această instanță a 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 = nul; MiniDaemon.prototype.rate = 100; MiniDaemon.prototype.length = Infinit;< 1: this.INDEX + 1 >aceasta.lungime; ); MiniDaemon.prototype.synchronize = function () ( if (this.PAUSED) ( return; ) clearInterval(this.SESSION); this.SESSION = setInterval(MiniDaemon.forceCall, this.rate, this); ); MiniDaemon.prototype.pause = function () ( clearInterval(this.SESSION); this.PAUSED = true; ); MiniDaemon.prototype.start = funcție (bReverse) ( var bBackw = Boolean(bReverse); if (this.BACKW === bBackw && (this.isAtEnd() || !this.PAUSED)) ( return; ) this.BACKW = bBackw; this.PAUSED = false.synchronize();

MiniDaemon transmite argumente funcției de apel invers. Dacă doriți să lucrați la el cu browsere care în mod nativ nu acceptă această caracteristică, utilizați una dintre metodele propuse mai sus.

Sintaxă

var myDaemon = new MiniDaemon( acestObiect, sună din nou[ , rata [, lungime]]);

Descriere Note de utilizare

Funcția setInterval() este folosită în mod obișnuit pentru a seta o întârziere pentru funcțiile care sunt executate din nou și din nou, cum ar fi animațiile. Puteți anula intervalul folosind WindowOrWorkerGlobalScope.clearInterval() .

Dacă doriți să vă apelați funcția dată după întârzierea specificată, utilizați .

Restricții de întârziere

Este posibil ca intervalele să fie imbricate; adică callback-ul pentru setInterval() poate, la rândul său, apela setInterval() pentru a începe să ruleze un alt interval, chiar dacă primul este încă în curs. Pentru a atenua impactul potențial pe performanță, odată ce intervalele sunt imbricate peste cinci niveluri, browserul va aplica automat o valoare minimă de 4 ms pentru interval. Încercările de a specifica o valoare mai mică de 4 ms în apelurile imbricate profund la setInterval() vor fi fixate la 4 ms.

Browserele pot impune valori minime și mai stricte pentru interval în anumite circumstanțe, deși acestea nu ar trebui să fie comune. Rețineți, de asemenea, că timpul real care se scurge între apeluri la apel invers poate fi mai mare decât întârzierea dată; vedeți Motive pentru întârzieri mai mari decât cele specificate în WindowOrWorkerGlobalScope.setTimeout() pentru exemple.

Asigurați-vă că durata execuției este mai mică decât frecvența intervalului

Dacă există posibilitatea ca logica dvs. să dureze mai mult decât intervalul de timp, este recomandat să apelați recursiv o funcție numită folosind setTimeout() . De exemplu, dacă utilizați setInterval() pentru a interoga un server la distanță la fiecare 5 secunde, latența rețelei, un server care nu răspunde și o serie de alte probleme ar putea împiedica finalizarea cererii în timpul alocat. Ca atare, s-ar putea să vă aflați cu solicitări XHR puse în coadă care nu vor reveni neapărat în ordine.

În programarea în limbaje de scripting, există periodic necesitatea de a crea o pauză - de a întrerupe execuția programului pentru un timp și apoi de a continua lucrul. De exemplu, în scripturile VBS și PHP sunt posibile următoarele metode:

VBS: wscript.sleep 1500 (oprire timp de 1,5 secunde)

PHP: sleep(10); (oprire 10 secunde)

În timpul unor astfel de pauze, sistemul de rulare (PHP sau VBS) nu face nimic. Un dezvoltator care încearcă să folosească intuitiv ceva similar în Javascript va fi surprins neplăcut. Greșeală comună când încercați să creați o pauză în Javascript, arată astfel:

Funcția badtest() (pentru (var i=1; i< 10; i++) { window.setTimeout("document.getElementById("test1").value += " + i, 900) } }

Crezi că atunci când, în timpul buclei, vine rândul să trageți următorul număr, setTimeout-ul dvs. va opri sincer să funcționeze JavaScript, așteptați 0,9 secunde, adăugați numărul dorit la sfârșitul câmpului de introducere și apoi continuați să lucrați. Dar, în realitate, acesta nu este cazul: setInterval și setTimeout în Javascript întârzie doar execuția acțiunii (sau funcției) specificate în paranteze. În exemplul nostru, se va întâmpla următoarele:

  • i = 1;
  • întârzie adăugarea numărului „1” în câmpul de intrare cu 0,9 secunde;
  • Imediat după setarea acestei probleme, ciclul continuă: i=2;
  • întârzie adăugarea numărului „2” în câmpul de intrare cu 0,9 secunde;
  • Imediat înseamnă, de exemplu, 1 ms (adică disproporționat de mic față de 900 ms): bucla își va face treaba aproape instantaneu, creând mai multe sarcini amânate din același moment în timp. Aceasta înseamnă că toate sarcinile de „desen” în așteptare vor fi finalizate aproape în același timp, fără pauze între adăugarea de noi numere. Ciclul începe; totul îngheață timp de 0,9 s; și shirr - toate numerele sunt împușcate la rând unul după altul.

    Cum se aplică corect setTimeout într-un astfel de caz? E complicat. Va trebui să apelați funcția recursiv(din cadrul funcției aceeași funcție) și pentru ca acest proces să nu fie nesfârșit, setați o condiție de oprire (de exemplu, dimensiunea numărului care trebuie tipărit):

    Funcția welltest() (dacă (i< 9) { document.getElementById("test2").value += ++i window.setTimeout("welltest()", 400) } }

    Și variabila i va trebui să fie inițializată în afara funcției - de exemplu, astfel:

    Acum totul funcționează așa cum ar trebui (am redus timpul de întârziere de la 0,9 s la 0,4 s). Dar pentru astfel de sarcini, este mai logic să folosiți setInterval mai degrabă decât setTimeout (deși acest lucru va necesita două funcții):

    Funcția besttest() ( window.i = 0 window.timer1 = window.setInterval("draw()", 400) ) function draw() ( document.getElementById("test3").value += ++i if (i >= 9) clearInterval(window.timer1) )

    Particularitatea metodei Javascirpt setInterval este că nu trece „de la sine”, trebuie oprită cu o metodă specială clearInterval. Și pentru a clarifica ce anume trebuie oprit, sarcinii pentru acțiunea amânată i se atribuie un identificator special - un temporizator: window.timer1 = window.setInterval(...) .

    Identificatorii pot fi, de asemenea, alocați sarcinilor create prin metoda setTimeout. Toate ID-urile temporizatorului trebuie să fie distincte unele de altele (unice în fereastra curentă a browserului). Apoi puteți crea mai multe sarcini diferite în fereastră care folosesc acțiuni amânate, iar aceste sarcini vor fi executate în paralel (un fel de simultan, dacă computerul are suficiente resurse), ceea ce este practic imposibil în PHP sau VBS.

    Iată un exemplu de pagină cu mai multe temporizatoare Javascript care rulează simultan: setinterval.htm (funcții Javascript în fișierul setinterval.js). Toate temporizatoarele de pagină (cu excepția meniului) pot fi oprite folosind tasta Esc. Toate exemplele de cronometre se bazează pe o numărătoare inversă „naturală” (și nu abstractă i++) - timp sau distanță. Toate „ceasurile” sunt special desincronizate (pentru claritate). Cronometrele dependente de distanță sunt utilizate în „indicator” și în meniul drop-down („extras”).

    Meniu derulant

    Meniul nostru de alunecare este de fapt alunecat (de sub „antet”): spații sunt lăsate special între elemente, astfel încât să puteți vedea cum alunecă. În mod neașteptat, s-a dovedit că nu am putut face ieșirea la fel de lină pentru liste de lungimi diferite - probabil din cauza performanței scăzute a computerului (AMD Athlon 999 MHz).

    Este destul de evident că pentru frumusețe și armonie este necesar ca listele cu diferite elemente de meniu să apară în același timp. Adică, listele mai lungi ar trebui să renunțe cu mai multe de mare viteză, cele mai scurte - la o viteza mai mica. Se pare că ar putea fi implementat astfel:

  • Am setat timpul total de „plecare”, de exemplu, la 200 ms.
  • Dacă lista derulantă are o înălțime de 20 px, este evident că o putem deplasa în jos cu un pixel la un interval de 10 ms - și apoi în 200 ms va ieși întreaga listă.
  • Dacă meniul derulant are o înălțime de 40 de pixeli, pentru a se potrivi în aceeași perioadă de timp, trebuie să îl deplasăm în jos cu un pixel la fiecare 5 ms.
  • După această logică, dacă lista verticală are o înălțime de 200 de pixeli, ar trebui să o mutăm în jos cu un pixel la fiecare 1 ms. Dar o astfel de viteză nu funcționează pe computerul nostru - browserul pur și simplu nu are timp să deseneze noua poziție a listei într-o milisecundă. Da. Javascript reușește să numere (ce este acolo de numărat?), dar browserul (Firefox) nu are timp să se afișeze. Situație tipică pentru web.

    Prin urmare, este posibil să egalizați mai mult sau mai puțin ora de plecare a meniului numai cu ajutorul cârjelor și încă nu este clar cum va funcționa acest lucru pentru mai mult. calculator rapid. Dar ar trebui să ne bazăm pe cel mai lent, nu? Algoritmul (fără a ține cont de viteza computerului) rezultă cam așa:

  • Setați timpul total pentru verificarea listei: timp = 224 (ms).
  • Setăm timpul minim pentru un interval din ciclu: întârziere = 3 (ms).
  • Setați pasul minim pentru mutarea listei: offset = 1 (px).
  • Schimbăm toate acestea în funcție de înălțimea listei: 1) mărim timpul de întârziere (interval) invers proporțional cu înălțimea și direct proporțional cu timpul total de timp (la înălțimea de 224 coeficientul este 1); 2) dacă înălțimea este mai mare de 40 px, creșteți treapta minimă proporțional cu înălțimea. Constanta „40” a fost obținută experimental pentru cel mai lent computer. Testele pe un computer Pentium 4 CPU 2.53GHz au dezvăluit exact același număr - 40. În caz contrar, temporizatoarele se defectează, listele nu sunt în pas.
  • Acum listele apar mai mult sau mai puțin. Pentru timp mai mult sau mai puțin similar. Pe pagina setinterval.htm.

    Și iată că vine Bruce:

    Funcția 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 } } }

    Funcția în sine, care împinge listele imbricate din meniu, este, după cum putem vedea, foarte simplă. Tot ce rămâne este să-l rulezi cu ceva de genul acesta:

    Ts.timer1 = setInterval(function())(slide_do(ts, maxtop, offset)), întârziere)

    Ei bine, înainte de a începe, calculați toate aceste maxtop și offset și, de asemenea, plasați lista în poziția mintop. Aceasta este ceea ce face funcția slide() „preliminară” de 40 de linii. Și toate împreună - în fișierul setinterval.js. Da, și porcăria asta nu va funcționa deloc fără fișierul de stiluri inclus

    Este extrem de important să înțelegeți cum funcționează temporizatoarele JavaScript. Adesea, comportamentul lor nu se potrivește cu înțelegerea noastră intuitivă a multithreading-ului și acest lucru se datorează faptului că, în realitate, sunt executate într-un singur thread. Să ne uităm la patru funcții cu care putem gestiona temporizatoarele:

    • var id = setTimeout(fn, delay); - Creează un temporizator simplu care va apela o anumită funcție după o anumită întârziere. Funcția returnează un ID unic cu care cronometrul poate fi întrerupt.
    • var id = setInterval(fn, delay); - Similar cu setTimeout, dar apelează continuu funcția la un interval dat (până la oprire).
    • clearInterval(id);, clearTimeout(id); - Acceptă un ID de cronometru (returnat de una dintre funcțiile descrise mai sus) și oprește execuția apelului invers"a.
    Ideea principală de luat în considerare este că acuratețea perioadei de întârziere a temporizatorului nu este garantată. Pentru început, browserul execută toate evenimentele JavaScript asincrone într-un singur fir (cum ar fi clicurile mouse-ului sau temporizatoarele) și numai în momentul în care este rândul evenimentului respectiv. Acest lucru este cel mai bine demonstrat de următoarea diagramă:

    Există destul de multe informații de preluat în această figură, dar înțelegerea acesteia vă va oferi o înțelegere mai profundă a modului în care funcționează asincronia JavaScript. Acest grafic reprezintă timpul pe verticală în milisecunde, blocurile albastre arată blocurile de cod JavaScript care au fost executate. De exemplu, primul bloc se execută în medie în 18 ms, un clic de mouse blochează execuția pentru aproximativ 11 ms etc.

    JavaScript poate executa doar o bucată de cod (datorită naturii execuției cu un singur fir), fiecare blocând executarea altor evenimente asincrone. Aceasta înseamnă că atunci când are loc un eveniment asincron (cum ar fi un clic de mouse, un apel de temporizator sau finalizarea unei cereri XMLHttp), acesta este adăugat la o coadă și executat mai târziu (implementarea variază în funcție de browser, desigur, dar să fim de acord cu numiți-o „coadă”).

    Pentru început, să ne imaginăm că în interiorul unui bloc JavaScript pornesc două temporizatoare: setTimeout cu o întârziere de 10 ms și setInterval cu aceeași întârziere. În funcție de momentul începerii cronometrului, acesta se va declanșa în momentul în care nu am finalizat încă primul bloc de cod. Rețineți, totuși, că nu se declanșează imediat (acest lucru nu este posibil din cauza firului unic). În schimb, funcția amânată este pusă în coadă și executată în următorul moment disponibil.

    De asemenea, în timpul execuției primului bloc JavaScript, apare un clic de mouse. Handler-ul pentru acest eveniment asincron (și este asincron pentru că nu îl putem prezice) nu poate fi executat imediat în acest moment, așa că ajunge și el într-o coadă, ca și cronometrul.

    După ce primul bloc de cod JavaScript a fost executat, browserul pune întrebarea „Ce așteaptă să fie executat?” ÎN în acest caz, Controlul de clic al mouse-ului și temporizatorul sunt într-o stare în așteptare. Browserul selectează unul dintre ele (managerul de clic) și îl execută. Cronometrul va aștepta următoarea bucată de timp disponibilă în coada de execuție.

    Rețineți că, în timp ce gestionarea clicurilor mouse-ului se execută, se declanșează primul interval de apel invers. La fel ca timer-callback, va fi pus în coadă. Cu toate acestea, rețineți că atunci când intervalul se declanșează din nou (în timp ce timer-callback rulează), acesta va fi eliminat din coadă. Dacă toate apelurile de tip interval ar fi puse în coadă în timp ce se execută o bucată mare de cod, aceasta ar avea ca rezultat o grămadă de funcții care așteaptă să fie apelate, fără perioade de întârziere între execuția lor. În schimb, browserele tind să aștepte până când nu mai există funcții lăsat în coadă înainte de a adăuga încă unul la coadă.

    Astfel, putem observa cazul în care a treia declanșare a intervalului-callback coincide cu momentul în care acesta este deja executat. Acest lucru ilustrează un punct important: intervalelor nu le pasă ce rulează în prezent, ele vor fi adăugate la coadă fără a ține cont de perioada de întârziere dintre execuții.

    În cele din urmă, după încheierea celui de-al doilea interval-callback, vom vedea că nu mai este nimic pentru a fi executat de motorul JavaScript. Aceasta înseamnă că browserul așteaptă din nou să apară noi evenimente asincrone. Acest lucru se va întâmpla la marcajul de 50 ms, unde interval-callback va funcționa din nou. În acest moment nu va exista nimic care să-l blocheze, așa că va funcționa imediat.

    Să ne uităm la un exemplu care ilustrează frumos diferența dintre setTimeout și setInterval.
    setTimeout(function())( /* Un bloc lung de cod... */ setTimeout(arguments.callee, 10); ), 10);
    setInterval(function())( /* Un bloc lung de cod... */ ), 10);

    Aceste două opțiuni sunt echivalente la prima vedere, dar în realitate nu sunt. Codul care utilizează setTimeout va avea întotdeauna o întârziere de cel puțin 10 ms după apelul anterior (poate fi mai mult, dar niciodată mai puțin), în timp ce codul care utilizează setInterval va tinde să fie apelat la fiecare 10 ms, indiferent de momentul în care a avut loc apelul anterior.
    Să rezumăm tot ce s-a spus mai sus:
    - Funcțiile setTimeout și setInterval sunt executate fundamental diferit în codul asincron,
    - Dacă cronometrul nu poate fi executat în în acest moment, va fi amânată până la următorul punct de execuție (care va fi mai mare decât întârzierea dorită),
    - Intervalele (setInterval) pot fi executate unul după altul fără întârziere dacă executarea lor durează mai mult decât întârzierea specificată.

    Toate acestea sunt extrem de informatii importante pentru dezvoltare. Cunoașterea modului în care funcționează motorul JavaScript, în special cu o mulțime de evenimente asincrone (ceea ce se întâmplă adesea), pune o bază excelentă pentru construirea de aplicații avansate.

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

    Aproape toate implementările JavaScript au un programator de temporizator intern care vă permite să programați o funcție pentru a fi apelată după o anumită perioadă de timp.

    În special, această caracteristică este acceptată în browsere și în serverul Node.JS.

    setTimeout

    Sintaxă:

    var timerId = setTimeout(functie/cod, delay[, arg1, arg2...])

    Parametri:

    • func/cod
      • O funcție sau linie de cod care urmează să fie executată.
      • Șirul este menținut pentru compatibilitate și nu este recomandat.
    • func
      • Latența în milisecunde, 1000 de milisecunde este egal cu 1 secundă.
    • arg1, arg2...
      • Argumente de trecut la funcție. Nu este acceptat în IE9-.
      • Funcția va fi executată după timpul specificat în parametrul de întârziere.

    De exemplu, următorul cod va declanșa alerta ("Bună ziua") după o secundă:

    function func () ( alert("Bună ziua"); ) setTimeout(func, 1000);

    Dacă primul argument este un șir, atunci interpretul creează o funcție anonimă din acel șir.

    Adică, această intrare funcționează exact la fel:

    SetTimeout("alertă("Bună ziua")" , 1000 );

    Utilizați în schimb funcții anonime:

    SetTimeout(funcție () ( alert("Bună ziua" ) ), 1000 );

    Parametri pentru funcție și context

    În toate browsere moderne Având în vedere IE10, setTimeout vă permite să specificați parametrii funcției.

    Exemplul de mai jos va afișa „Bună ziua, sunt Vasya” peste tot, cu excepția IE9-:

    funcția sayHi (cine) ( alert("Bună ziua, sunt " + cine); ) setTimeout(spune Salut, 1000, "Vasya");

    ...Totuși, în majoritatea cazurilor avem nevoie de suport de la vechiul IE și nu vă permite să specificați argumente. Prin urmare, pentru a le transfera, aceștia înglobează apelul într-o funcție anonimă:

    funcția sayHi (cine) ( alert("Bună, eu sunt " + cine); ) setTimeout(funcție () ( sayHi ("Vasya") ), 1000 );

    Apelarea setTimeout nu trece acest context.

    În special, apelarea unei metode obiect prin setTimeout va funcționa în context global. Acest lucru poate duce la rezultate incorecte.

    De exemplu, să apelăm user.sayHi() după o secundă:

    function User (id) function () ( alert(this .id); ); ) var user = utilizator nou(12345); setTimeout(user.sayHi, 1000); // aștept 12345, dar va scoate „nedefinit”

    Deoarece setTimeout va rula funcția user.sayHi în context global, nu va avea acces la obiect prin acest .

    Cu alte cuvinte, aceste două apeluri la setTimeout fac același lucru:

    // (1) o linie setTimeout(user.sayHi, 1000); // (2) același lucru în două rânduri var func = user.sayHi; setTimeout(func, 1000);

    Din fericire, această problemă se rezolvă ușor prin crearea unei funcții intermediare:

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

    O funcție de wrapper este utilizată pentru a transmite argumente între browsere și pentru a păstra contextul de execuție.

    Anularea executiei

    Funcția setTimeout returnează un timerId care poate fi folosit pentru a anula acțiunea.

    Sintaxă:

    ClearTimeout(timerId)

    În exemplul următor, setăm un timeout și apoi ștergem (ne-am răzgândit). Drept urmare, nu se întâmplă nimic.

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

    Metoda setInterval are o sintaxă similară setTimeout.

    var timerId = setInterval(functie/cod, delay[, arg1, arg2...])

    Sensul argumentelor este același. Dar, spre deosebire de setTimeout , nu rulează funcția o dată, ci o repetă în mod regulat la un interval de timp specificat. Puteți opri execuția apelând:

    ClearInterval(timerId)

    Următorul exemplu, când este rulat, va afișa un mesaj la fiecare două secunde până când faceți clic pe butonul Stop:

    var i = 1 ;

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

    Apeluri în coadă și suprapunere în setInterval

    Apelul setInterval(funcție, întârziere) face ca funcția să fie executată la intervalul de timp specificat. Dar există o subtilitate aici.

    De fapt, pauza dintre apeluri este mai mică decât intervalul specificat.

    Adică browserul inițiază lansarea funcției ordonat la fiecare 100ms, fără a ține cont de timpul de execuție al funcției în sine.

    Se întâmplă ca execuția unei funcții să dureze mai mult decât întârzierea. De exemplu, funcția este complexă, dar întârzierea este mică. Sau funcția conține instrucțiuni de alertă / confirmare / prompt care blochează firul de execuție. Aici lucrurile încep să devină interesante.

    Dacă o funcție nu poate fi lansată deoarece browserul este ocupat, aceasta va fi pusă în coadă și executată imediat ce browserul este liber.

    Imaginea de mai jos ilustrează ce se întâmplă cu o funcție care durează mult timp pentru a fi executată.

    Apelul funcției inițiat de setInterval este adăugat la coadă și are loc imediat când este posibil:

    A doua lansare a funcției are loc imediat după sfârșitul primei:

    Execuția nu este pusă în coadă de mai multe ori.

    Dacă o funcție durează mai mult decât mai multe execuții programate, va rămâne în coadă o dată. Deci nu există „acumulare” de lansări.

    În imaginea de mai jos, setInterval încearcă să execute funcția în 200 ms și pune apelul în coadă. La 300ms și 400ms cronometrul se trezește din nou, dar nu se întâmplă nimic.

    Apelarea setInterval(funcție, întârziere) nu garantează întârzierea reală între execuții.

    Există cazuri când întârzierea reală este mai mare sau mai mică decât cea specificată. În general, nu este un fapt că va exista cel puțin o oarecare întârziere.

    Se repetă setTimeout imbricat

    În cazurile în care nu este necesară doar repetarea regulată, ci este necesară o întârziere între rulări, setTimeout este folosit pentru a reseta de fiecare dată când funcția este executată.

    Mai jos este un exemplu care emite o alertă cu intervale de 2 secunde între ele.

    var i = 1 ;

    var timer = setTimeout(funcția run () ( alert(i++); timer = setTimeout(run, 2000 ); ), 2000 );

    Cronologia de execuție va avea întârzieri fixe între rulări. Ilustrație pentru întârziere de 100 ms:

    Întârziere minimă a temporizatorului

    Cronometrul browserului are cea mai mică latență posibilă. Acesta variază de la aproximativ zero la 4 ms în browserele moderne. La cele mai vechi poate fi mai lung și ajunge la 15ms.

    Conform standardului, întârzierea minimă este de 4 ms. Deci, nu există nicio diferență între setTimeout(..,1) și setTimeout(..,4) .

  • Comportamentul cu latență zero al setTimeout și setInterval este specific browserului.
  • În Internet Explorer, zero delay setInterval(.., 0) nu va funcționa. Acest lucru se aplică în mod specific setInterval , adică. setTimeout(.., 0) funcționează bine.
  • Frecvența reală de declanșare

    Declanșarea poate fi mult mai puțin frecventă În unele cazuri, întârzierea poate să nu fie de 4 ms, ci de 30 ms sau chiar de 1000 ms.

    Majoritatea browserelor (în primul rând cele de desktop) continuă să execute setTimeout / setInterval chiar dacă fila este inactivă. În același timp, un număr dintre ele (Chrome, FF, IE10) reduc frecvența minimă a temporizatorului la 1 dată pe secundă. Se pare că cronometrul va funcționa în fila „de fundal”, dar rar.

    Când rulează pe baterie, pe un laptop, browserele pot, de asemenea, să reducă frecvența pentru a executa codul mai rar și a economisi energia bateriei. IE este deosebit de renumit pentru asta. Reducerea poate ajunge de mai multe ori, în funcție de setări. Dacă încărcarea procesorului este prea mare, este posibil ca JavaScript să nu poată procesa temporizatoarele în timp util. Acest lucru va omite unele rulări setInterval.

    Concluzie: pe o frecvență de 4 ms merită să te concentrezi, dar nu ar trebui să te bazezi pe ea.

    Ieșirea intervalelor către consolă Codul care numără intervalele de timp dintre apeluri arată cam așa:

    var timeMark = data noua; setTimeout(funcția go () ( var diff = new Date - timeMark; // imprimă următoarea întârziere pe consolă în locul consolei paginii .log(diff); // amintim ora de la sfârșit, // pentru a măsura întârziere între apeluri timeMark = new Date ; setTimeout(go, 100 ), 100 ; Trucul este setTimeout(func, 0)

    Acest truc este demn de a intra în analele hackurilor JavaScript.

    Funcția este încapsulată în setTimeout(func, 0) dacă doriți să o rulați după sfârșitul scriptului curent.

    Chestia este că setTimeout nu execută niciodată funcția imediat. El plănuiește doar implementarea acesteia. Dar interpretul JavaScript va începe să execute funcțiile planificate numai după ce scriptul curent este executat.

    Conform standardului, setTimeout nu poate executa oricum o funcție cu o întârziere de 0 Așa cum am spus mai devreme, întârzierea va fi de obicei de 4 ms. Dar principalul lucru aici este că execuția, în orice caz, va avea loc după executarea codului curent.

    De exemplu:

    var rezultat; funcția showResult () ( alertă(rezultat); ) setTimeout(showResult, 0); rezultat = 2 *2 ; // va scoate 4 Total

    Metodele setInterval(func, delay) și setTimeout(func, delay) vă permit să rulați func în mod regulat/o dată la fiecare întârziere în milisecunde.

    Ambele metode returnează ID-ul temporizatorului. Este folosit pentru a opri execuția apelând clearInterval/clearTimeout.

    | | setInterval | setTimeout | || ----------- | ---------- | | Timp | Apelul este strict pe un cronometru. Dacă interpretul este ocupat, un apel este pus în coadă. Timpul de execuție a funcției nu este luat în considerare, astfel încât intervalul de timp de la sfârșitul unei rulări până la începutul alteia poate varia. | Apelul recursiv la setTimeout este folosit în loc de setInterval unde este necesară o pauză fixă ​​între execuții. | | Întârziere | Întârziere minimă: 4 ms. | Întârziere minimă: 4 ms. | | Caracteristici browser | Latența 0 nu funcționează în IE În Opera, latența zero este echivalentă cu 4 ms, alte întârzieri sunt gestionate cu precizie, inclusiv 1 ms, 2 ms și 3 ms non-standard. |

    © 2024 ermake.ru -- Despre repararea PC-ului - Portal de informații