Internet Windows Android

Javascript împiedică executarea simultană a mai multor temporizatoare setinterval. Temporizatoare în Javascript (setInterval, setTimeout)

Timpul JavaScript este o funcție nativă javascript care execută o bucată de cod după o întârziere specificată (în milisecunde). Acest lucru poate fi util când trebuie să afișați un popup după ce utilizatorul a petrecut ceva timp pe pagina dvs. Sau doriți ca efectul să înceapă atunci când plasați cursorul peste un element numai după ceva timp. În acest fel, puteți evita declanșarea accidentală a efectului dacă utilizatorul trece peste un accident.

Exemplu simplu setTimeout

Pentru a demonstra efectul acestei funcții, vă sugerez să aruncați o privire la următoarea demonstrație, în care apare o fereastră pop-up la două secunde după ce butonul este făcut clic.

Vizualizați demonstrația

Sintaxă

Documentația MDN oferă următoarea sintaxă pentru setTimeout:

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

  • timeoutID este un ID numeric care poate fi utilizat împreună cu clearTimeout () pentru a dezactiva temporizatorul;
  • func este funcția care trebuie executată;
  • cod ( în sintaxă alternativă) - linia de cod de executat;
  • întârziere - durata întârzierii în milisecunde după care funcția va rula. Valoarea implicită este 0.

setTimeout vs window.setTimeout

Sintaxa de mai sus folosește window.setTimeout. De ce?

De fapt, setTimeout și window.setTimeout sunt practic aceeași funcție. Singura diferență este că în a doua afirmație, folosim metoda setTimeout ca proprietate a obiectului fereastră globală.

Personal, cred că acest lucru complică mult codul. Dacă ar fi să definim o metodă alternativă de expirare JavaScript care poate fi găsită și returnată în ordine de prioritate, am întâmpina probleme și mai mari.

În acest tutorial, nu vreau să mă încurc cu obiectul ferestrei, dar, în general, decideți ce sintaxă să utilizați.

Exemple de utilizare

Acesta ar putea fi numele funcției:

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

Variabilă care se referă la funcția:

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

Sau o funcție anonimă:

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

  • Un astfel de cod este slab înțeles și, prin urmare, va fi dificil de modernizat sau depanat;
  • Aceasta implică utilizarea metodei eval (), care ar putea fi o potențială vulnerabilitate;
  • Această metodă este mai lentă decât altele, deoarece trebuie să ruleze Interpret JavaScript.

De asemenea, rețineți că folosim metoda de alertă pentru expirarea JavaScript pentru a testa codul.

Trecerea parametrilor la setTimout

In primul ( în plus, cross-browser), trecem parametrii la funcția de apel invers executată cu setTimeout.

În exemplul următor, extragem o felicitare aleatorie din matricea de felicitări și o transmitem ca parametru funcției greet (), care este executată de setTimeout cu o întârziere de 1 secundă:

function greet (greeting) (console.log (greeting);) function getRandom (arr) (return arr;) var greetings = ["Hello", "Bonjour", "Guten Tag"], randomGreeting = getRandom (salutări); setTimeout (function () (greet (randomGreeting);), 1000);

Vizualizați demonstrația

Metoda alternativă

În sintaxa de la începutul acestui articol, există o altă metodă care poate fi utilizată pentru a transmite parametrii funcției de apel invers executată prin expirarea JavaScript. Această metodă implică ieșirea tuturor parametrilor după întârziere.

Bazându-ne pe exemplul anterior, obținem:

setTimeout (greet, 1000, randomGreeting);

Această metodă nu va funcționa în IE 9 și mai jos, unde parametrii trecuți sunt nedefiniți. Dar pentru a rezolva această problemă pe MDN are o poliamplură specială.

Probleme conexe și „asta”

Codul executat de setTimeout rulează separat de funcția care l-a numit. Din această cauză, ne confruntăm cu anumite probleme, acest cuvânt cheie poate fi folosit ca soluție.

var person = (firstName: "Jim", introduce: function () (console.log ("Hi, I" m "+ this.firstName);)); person.introduce (); // Outputs: Hi, I" m Jim setTimeout (person.introduce, 50); // Ieșiri: Bună, sunt nedefinit

Motivul acestei concluzii constă în faptul că în primul exemplu acest lucru duce la obiectul persoană, iar în al doilea exemplu indică obiectul fereastră globală, care nu are proprietatea firstName.

Pentru a scăpa de această inconsecvență, puteți utiliza mai multe metode:

Forțați setarea acestei valori

Acest lucru se poate face folosind bind (), o metodă care creează o nouă funcție care, atunci când este apelată ca valoare a acestei chei, utilizează o valoare specifică. În cazul nostru, persoana specificată obiectează. Acest lucru ne oferă ca rezultat:

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

Notă: bind a fost introdus în ECMAScript 5, ceea ce înseamnă că va funcționa doar în browserele moderne. În altele, veți primi o eroare de execuție atunci când o aplicați JavaScript "eroare timeout funcție".

Folosiți biblioteca

Multe biblioteci includ funcții încorporate necesare pentru rezolvarea acestei probleme. De exemplu, metoda jQuery.proxy (). Acesta ia o funcție și returnează una nouă, în care va folosi întotdeauna un context specific. În cazul nostru, contextul va fi:

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

Vizualizați demonstrația

Dezactivați temporizatorul

Valoarea returnată a setTimeout este un ID numeric care poate fi utilizat pentru a dezactiva cronometrul folosind funcția clearTimeout ():

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

Să o vedem în acțiune. În exemplul următor, dacă faceți clic pe butonul „ Porniți numărătoarea inversă”, Începe numărătoarea inversă. După ce s-a terminat, pisoii vor primi al lor. Dar dacă apăsați butonul " Opriți numărătoarea inversă", Timpul expirat JavaScript va fi oprit și resetat.

Vedeți exemplul

Să rezumăm

setTimeout este o funcție asincronă, ceea ce înseamnă că apelul primit către această funcție este pus în coadă și va fi executat numai după ce toate celelalte acțiuni din stivă s-au finalizat. Nu poate rula concomitent cu alte funcții sau un fir separat.

The 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 ulterior apelând clearInterval (). Această metodă este definită de mixul WindowOrWorkerGlobalScope.

Sintaxă

var intervalID = scop.setInterval ( func, întârziere, [arg1, arg2, ...]); var intervalID = scop.setInterval ( cod, întârziere);

Parametrii

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 de returnare. 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 întârziere în milisecunde. Această sintaxă este Nu se recomandă din aceleași motive care fac din utilizarea eval () un risc de securitate. întârziere Timpul, în milisecunde (miimi 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 func după expirarea temporizatorului.

Notă: Trecerea argumentelor suplimentare la setInterval () în prima sintaxă nu funcționează în Internet Explorer 9 și versiunile anterioare. Dacă doriți să activați această funcționalitate în browserul respectiv, trebuie să utilizați un polyfill (consultați secțiunea).

Valoare returnată

ID-ul intervalului returnat este o valoare numerică, diferită de zero, care identifică temporizatorul creat de apel pentru setInterval (); această valoare poate fi transmisă pentru a anula expirarea.

Poate fi util să fiți conștienți de faptul că setInterval () și setTimeout () împărtășesc același grup de ID-uri și că clearInterval () și clearTimeout () pot fi utilizate tehnic în mod interschimbabil. Cu toate acestea, pentru claritate, ar trebui să încercați să le potriviți întotdeauna pentru a evita confuzia atunci când vă mențineți codul.

Notă: Argumentul întârzierii este convertit într-un întreg semnat pe 32 de biți. Acest lucru limitează efectiv întârzierea la 2147483647 ms, deoarece este specificat ca număr întreg semnat în IDL.

Exemple

Exemplul 1: sintaxa de bază

Următorul exemplu demonstrează sintaxa de bază a setInterval ().

Var intervalID = window.setInterval (myCallback, 500, "Parameter 1", "Parameter 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.

setInterval / clearInterval exemplu

Salut Lume



Exemplul 3: Simularea mașinii de scris

Următorul exemplu simulează mașina de scris, mai întâi ștergând și apoi tastând încet conținut în NodeList care se potrivește cu un grup specificat de selectoare.

JavaScript Typewriter - Exemplu MDN

CopyLeft 2012 de Mozilla Developer Network

[ Joaca | Pauză | Termină ]

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. În tincidunt tincidunt tincidunt.

Mașină de scris JavaScript

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 nec velit in dolor tincidunt rhoncus non non diam. Morbi auctor ornare orci, non euismod felis gravida nec. Curabitur elementum nisi a eros rutrum nec blandit diam placerat. Aenean tincidunt risus ut nisi consectetur cursus. Ut vitae quam elit. Donec dignissim est in quam tempor consequat. Aliquam aliquam diam non felis convallis suscipit. Nulla facilisi. Donec lacus risus, dignissim et fringilla et, egestas vel eros. Duis malesuada accumsan dui, at fringilla mauris bibStartum quis. Cras adipiscing ultricies fermentum. Praesent bibStartum condimentum feugiat.

Nam faucibus, ligula eu fringilla pulvinar, lectus tellus iaculis nunc, vitae scelerisque metus leo non metus. Proin mattis lobortis lobortis. Quisque accumsan faucibus erat, vel varius tortor ultricies ac. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec libero nunc. Nullam tortor nunc, elementum a consectetur et, ultrices eu orci. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a nisl eu sem vehicula egestas.



Argumente de apel invers

După cum sa discutat anterior, versiunile Internet Explorer 9 și mai jos nu acceptă trecerea argumentelor la funcția de apel invers fie în setTimeout (), fie în setInterval (). Următoarele Specific IE codul demonstrează o metodă pentru depășirea acestei limitări. Pentru utilizare, pur și simplu adăugați următorul cod în partea de sus a scriptului.

/ * \ | * | | * | Poliplență specifică IE care permite trecerea argumentelor arbitrare la | * | funcții de apelare inversă a cronometrelor javascript (sintaxă standard HTML5) .. setInterval | * | https: // site / User: 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); | * | \ * / if (document.all &&! window.setTimeout.isPolyfill) (var __nativeST__ = window.setTimeout; window.setTimeout = funcție (vCallback, nDelay / *, argumentToPass1, argumentToPass2, etc. * /) (var aArgs = Array .prototype.slice.call (arguments, 2); return __nativeST __ (vCallback instanceof Function? function () (vCallback.apply (null, aArgs);): vCallback, nDelay);); window.setTimeout.isPolyfill = true; ) 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 Function? function () (vCallback.apply (null, aArgs);): vCallback, nDelay);); window.setInterval.isPolyfill = true;)

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

Var intervalID = setInterval (function () (myFunc ("one", "two", "three");), 1000); var intervalID = setInterval (function (arg1) () .bind (nedefinit, 10), 1000);

Filele 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 blocate pentru a declanșa nu mai des de o dată pe secundă în filele inactive.

Problema „aceasta”

Când treceți o metodă pentru 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

Codul executat de setInterval () rulează într-un context de execuție separat decât funcția din care a fost apelat. În consecință, acest cuvânt cheie pentru funcția apelată este setat la obiectul window (sau global), nu este același cu valoarea this pentru funcția care a numit setTimeout. Vedeți următorul exemplu (care folosește setTimeout () în loc de setInterval () - problema, de fapt, este aceeași pentru ambele temporizatoare):

MyArray = ["zero", "one", "two"]; myArray.myMethod = function (sProperty) (alert (arguments.length> 0? this: this);); myArray.myMethod (); // tipărește „zero, unu, doi” myArray.myMethod (1); // tipărește "one" setTimeout (myArray.myMethod, 1000); // tipărește "" după 1 secundă setTimeout (myArray.myMethod, 1500, "1"); // tipărește „nedefinit” după 1,5 secunde // trece obiectul „acest” cu .call câștigat „să nu funcționeze // deoarece acest lucru va schimba valoarea acestui setTimeout din interior // în timp ce vrem să schimbăm valoarea acestui în myArray .myMethod // de fapt, va fi o eroare deoarece codul setTimeout se așteaptă ca acesta să fie obiectul ferestrei: setTimeout.call (myArray, myArray.myMethod, 2000); // error: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Operație ilegală pe obiectul prototip WrappedNative" setTimeout.call (myArray, myArray.myMethod, 2500, 2); // aceeași eroare

După cum puteți vedea, nu există modalități de a transmite acest obiect funcției de apel invers în javascriptul vechi.

O posibilă soluție

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

// Activați trecerea obiectului „acesta” prin cronometrele 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? function () (vCallback.apply (oThis, aArgs);): vCallback, nDelay);); window.setInterval = function (vCallback, nDelay / *, argumentToPass1, argumentToPass2, etc. * /) (var oThis = this, aArgs = Array.prototype.slice.call (arguments, 2); return __nativeSI __ (vCallback instanceof Function? function () (vCallback.apply (oThis, aArgs);): vCallback, nDelay););

Aceste două înlocuiri permit, de asemenea, trecerea standard HTML5 a argumentelor arbitrare către funcțiile de callback ale cronometrelor din IE. Deci pot fi folosite ca neconforme standardelor polifenituri, de asemenea. A se vedea pentru conform standardului polifund.

Test de funcții noi:

MyArray = ["zero", "one", "two"]; myArray.myMethod = function (sProperty) (alert (arguments.length> 0? this: this);); setTimeout (alertă, 1500, „Bună ziua lume!”); // se utilizează standard setTimeout și setInterval, dar ... setTimeout.call (myArray, myArray.myMethod, 2000); // tipărește „zero, unu, doi” după 2 secunde setTimeout.call (myArray, myArray.myMethod, 2500, 2); // tipărește „doi” după 2,5 secunde

Pentru o versiune mai complexă, dar încă modulară a acestuia ( Daemon) vezi JavaScript Daemons Management. Această versiune mai complexă nu este altceva decât o colecție mare și scalabilă de metode pentru Daemon constructor. Însă Daemon constructorul în sine nu este altceva decât o clonă a MiniDaemon cu un suport adăugat pentru initși la început funcții declarabile în timpul instanțierii daemon . Asa ca MiniDaemon cadrul rămâne modul recomandat pentru animații simple, deoarece Daemon fără colecția sa de metode este în esență o clonă a acesteia.

minidaemon.js

/ * \ | * | | * | :: MiniDaemon :: | * | | * | Revizuirea nr. 2 - 26 septembrie 2014.setInterval | * | https: // site / User: fusionchess | * | https://github.com/madmurphy/minidaemon.js | * | | * | Acest cadru este lansat sub licența GNU Lesser General Public License, versiunea 3 sau o versiune ulterioară. | * | http://www.gnu.org/licenses/lgpl-3.0.html | * | \ * / function MiniDaemon (oOwner, fTask, nRate, nLen) (if (! (this && this instanceof 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 = nul; MiniDaemon.prototype.task = nul; MiniDaemon.prototype.rate = 100; MiniDaemon.prototype.length = Infinity; / * Aceste proprietăți ar trebui să fie numai în citire * / MiniDaemon.prototype.SESSION = -1; MiniDaemon.prototype.INDEX = 0; MiniDaemon.prototype.PAUSED = adevărat; MiniDaemon.prototype.BACKW = adevărat; / * Metode globale * / MiniDaemon.forceCall = function (oDmn) (oDmn.INDEX + = oDmn.BACKW? -1: 1; if (oDmn.task.call (oDmn.owner, oDmn.INDEX, oDmn.length, oDmn .BACKW) === false || oDmn.isAtEnd ()) (oDmn.pause (); return false;) return true;); / * Metode de instanțe * / MiniDaemon.prototype.isAtEnd = function () (returnează this.BACKW? IsFinite (this.length) && this.INDEX< 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 = function (bReverse) (var bBackw = Boolean (bReverse); if (this.BACKW === bBackw && (this.isAtEnd () ||! This.PAUSED)) (return;) this.BACKW = bBackw; this.PAUSED = false; this.synchronize (););

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

Sintaxă

var myDaemon = nou MiniDaemon ( thisObject, suna inapoi[ , rată [, lungime]]);

Descriere

Note de utilizare

Funcția setInterval () este frecvent utilizată 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 utilizând WindowOrWorkerGlobalScope.clearInterval ().

Dacă doriți să vi se apeleze funcția o singura data după întârzierea specificată, utilizați.

Restricții de întârziere

Este posibil ca intervalele să fie imbricate; adică apelarea inversă pentru setInterval () poate, la rândul său, să apeleze setInterval () pentru a începe să ruleze un alt interval, chiar dacă primul este încă în curs. Pentru a atenua impactul potențial pe care îl poate avea performanță, odată ce intervalele sunt imbricate dincolo de cinci niveluri de adâncime, browserul va aplica automat o valoare minimă de 4 ms pentru interval.

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 trece între apelurile către apelul de apel poate fi mai lung decât întârzierea dată; a se vedea Motivele întârzierilor mai lungi decât cele specificate în WindowOrWorkerGlobalScope.setTimeout () pentru exemple.

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

Dacă există posibilitatea ca logica dvs. să dureze mai mult pentru a se executa 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ă regăsiți cu cereri XHR în așteptare, care nu vor reveni neapărat în ordine.

  • Din:
  • Înregistrat: 2014.07.08
  • Postări: 3,896
  • Îi place: 497

Subiect: SetTimeOut și SetInterval, care este mai bine de utilizat în JavaScript?

Pentru a rula codul de mai multe ori la intervale regulate, utilizați funcția setInterval... Cu toate acestea, are o serie de dezavantaje, în principal comportament diferit în diferite browsere.

Prima diferență este diferența atunci când temporizatorul este setat pentru următorul start. Să creăm un mic test: vom măsura cantitatea de timp scurs de la începutul lansării anterioare și de la sfârșitul acesteia.

var d1 = data nouă (), d2 = data nouă (); setInterval (function () (var d = new Date (); document.body.innerHTML + = (d - d1) + "" + (d - d2) + "
"; // Puneți o etichetă la începutul funcției d1 = data nouă (); în timp ce (data nouă () - d1< 200); // ничего не делаем 200 миллисекунд // И в конце функции d2 = new Date(); }, 1000);

Ieșirea va fi informativă începând cu a doua linie.

În Firefox, Opera, Safari și Chrome, situația va fi similară: primul număr va fi aproximativ egal cu 1000, al doilea - 200 mai puțin. Diferența va fi doar în intervalul de valori. Cea mai mică variantă în Chrome și Opera.

2 Răspundeți de PunBB (editat de PunBB 2017.06.08 16:45)

  • Din: Moscova, Sovkhoznay 3, apt. 98
  • Înregistrat: 2014.07.08
  • Postări: 3,896
  • Îi place: 497

O altă diferență care este mai puțin vizibilă și mai dificil de reprodus, dar uneori poate provoca multe probleme, este rezistența la schimbări în timpul sistemului. Dacă rulați următorul test

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

Și după pornire, setați timpul sistemului înapoi cu un minut, apoi în browserele Firefox și Safari schimbarea numerelor se va întrerupe, iar după un minut va începe din nou. Desigur, traducerea manuală a timpului sistemului este o situație extrem de rară, dar multe sisteme sunt configurate pentru a sincroniza automat timpul cu serverele de pe Internet, deci în unele situații acest factor nu poate fi ignorat.

Un alt mic dezavantaj al funcției setInterval este că, pentru a putea opri acțiunea, trebuie să vă amintiți identificatorul său undeva, ceea ce nu este întotdeauna convenabil.

3 Răspundeți de PunBB

  • Din: Moscova, Sovkhoznay 3, apt. 98
  • Înregistrat: 2014.07.08
  • Postări: 3,896
  • Îi place: 497

Re: SetTimeOut și SetInterval, care este mai bine să utilizați în JavaScript?

Pentru a scăpa de dezavantajele setInterval, puteți utiliza setTimeout multiple.

O alternativă importantă la setInterval este setul recursiv setTimeout:

/ ** în loc de: var timerId = setInterval (function () (alert ("tick");), 2000); * / var timerId = setTimeout (funcție tick () (alert ("tick"); timerId = setTimeout (tick, 2000);), 2000);

În codul de mai sus, următoarea execuție este programată imediat după sfârșitul celei anterioare.

Recursive setTimeout este o metodă de sincronizare mai flexibilă decât setInterval, deoarece timpul până la următoarea execuție poate fi programat diferit, în funcție de rezultatele celei actuale.

De exemplu, avem un serviciu care sondează serverul pentru date noi la fiecare 5 secunde. Dacă serverul este supraîncărcat, puteți crește intervalul de interogare la 10, 20, 60 de secunde ... Și apoi îl puteți returna când totul este normalizat.

Dacă avem în mod regulat sarcini care încarcă procesorul, atunci putem estima timpul petrecut cu execuția lor și putem programa următoarea lansare mai devreme sau mai târziu.

4 Răspundeți de PunBB

  • Din: Moscova, Sovkhoznay 3, apt. 98
  • Înregistrat: 2014.07.08
  • Postări: 3,896
  • Îi place: 497

Re: SetTimeOut și SetInterval, care este mai bine să utilizați în JavaScript?

SetTimeout recursiv garantează o pauză între apeluri, setInterval nu.

Să comparăm cele două coduri. Primul folosește setInterval:

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

Al doilea folosește un setTimeout recursiv:

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

Cu setInterval, temporizatorul intern va declanșa exact la fiecare 100ms și va apela funcțiile (i):

Pauza reală între apelurile func cu setInterval este mai mică decât cea specificată în cod!

Acest lucru este firesc, deoarece durata de funcționare a funcției nu este luată în considerare în niciun fel, „mănâncă” o parte din interval.

Este, de asemenea, posibil ca func sa dovedit a fi mai complicat decât ne-am așteptat și a durat mai mult de 100 ms pentru a se executa.

În acest caz, interpretul va aștepta finalizarea funcției, apoi va verifica cronometrul și, dacă timpul pentru apelare setInterval a venit deja (sau a trecut), atunci următorul apel va avea loc imediat.

Dacă funcția durează mai mult decât pauza setInterval, atunci apelurile vor avea loc fără întrerupere.

5 Răspundeți de sempai

  • Din: Ierusalim
  • Înregistrat: 2015.06.02
  • Postări: 958
  • Îi place: 274

Re: SetTimeOut și SetInterval, care este mai bine să utilizați în JavaScript?

Totul depinde de sarcina la îndemână. Inițial, SetTimeOut este folosit pentru a porni cronometrul o dată și SetInterval pentru a porni bucla. Dar ambele funcții pot fi utilizate pentru a parcurge script-uri, dacă, de exemplu, rulează recursiv în funcția SetTimeOut, va acționa într-un mod practic similar cu SetInterval.

Dezavantajul SetInterval în acest moment este că nu ia în considerare timpul de execuție al scriptului (funcției) în sine și dacă, de exemplu, îl utilizați pentru solicitări mari, atunci intervalul de timp va fi redus semnificativ și pot diferi în diferite browsere.

Dar, din nou, repet, dacă funcția sau cererea este minimizată, atunci este puțin probabil ca utilizatorul final să simtă diferența.
Prin urmare, ce să folosească, fiecare decide singur.

Sursă: http://learn.javascript.ru/settimeout-setinterval

Aproape toate implementările JavaScript au un temporizator de planificare intern care vă permite să programați un apel funcțional după o perioadă de timp specificată.

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

setTimeout

Sintaxă:

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

Opțiuni:

  • func / code
    • O funcție sau o linie de cod de executat.
    • Șirul este acceptat pentru compatibilitate și este învechit.
  • întârziere
    • Întârziere în milisecunde, 1000 milisecunde este egală cu 1 secundă.
  • arg1, arg2 ...
    • Argumente pentru a trece 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 apela alertă („Bună ziua”) după o secundă:

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

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

Adică, o astfel de înregistrare funcționează exact la fel:

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

Folosiți în schimb funcții anonime:

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

Parametrii funcției și contextul

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

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

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

... Cu toate acestea, în majoritatea cazurilor avem nevoie de suport pentru vechiul IE și nu vă permite să specificați argumente. Prin urmare, pentru a le transmite, apelul este înfășurat într-o funcție anonimă:

funcție spune Salut (cine)(alert („Bună ziua, eu” + cine);) setTimeout ( funcție ()(sayHi ("Vasya")), 1000);

Apelarea prin setTimeout nu trece de 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ă:

funcție Utilizator (id) funcție ()(alertă (acest .id);); ) var utilizator = utilizator nou (12345); setTimeout (user.sayHi, 1000); // se aștepta la 12345, dar va imprima „nedefinit”

Deoarece setTimeout va rula funcția user.sayHi în context global, nu va putea accesa obiectul prin aceasta.

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ă este, de asemenea, ușor de rezolvat prin crearea unei funcții intermediare:

funcție Utilizator (id)(this .id = id; this .sayHi = funcție ()(alertă (acest .id);); ) var utilizator = utilizator nou (12345); setTimeout ( funcție ()(user.sayHi ();), 1000);

Funcția de împachetare este utilizată pentru a trece argumente de navigare încrucișată și pentru a stoca contextul de execuție.

Anulați execuția

Funcția setTimeout returnează un timerId care poate fi utilizat pentru a anula o acțiune.

Sintaxă:

ClearTimeout (timerId)

În exemplul următor, stabilim un timeout și apoi ștergem (ne răzgândim). Ca urmare, nu se întâmplă nimic.

var timerId = setTimeout ( funcție ()(alertă (1)), 1000); clearTimeout (timerId);

setInterval

Metoda setInterval are o sintaxă similară cu setTimeout.

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

Semnificația argumentelor este aceeași. Dar, spre deosebire de setTimeout, începe executarea funcției nu o dată, ci o repetă în mod regulat la un interval de timp specificat. Puteți opri executarea apelând:

ClearInterval (timerId)

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

<input type = "button" onclick = "clearInterval (timer)" value = "(! LANG: Stop" > !} <script> var i = 1; var timer = setInterval ( funcție ()(alert (i ++)), 2000);script>

Coada și suprapunerea apelurilor în setInterval

Apelarea setInterval (funcție, întârziere) pune funcția care trebuie executată după intervalul de timp specificat. Dar există o subtilitate aici.

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

De exemplu, să luăm setInterval (function () (func (i ++)), 100). Execută funcții la fiecare 100ms, incrementând contorul de fiecare dată.

În imaginea de mai jos, blocul roșu este timpul de execuție a func. Timpul dintre bloc este timpul dintre începutul funcției și este mai mic decât întârzierea setată!

Adică, browserul inițiază lansarea funcției cu grijă la fiecare 100ms, fără a lua în considerare timpul de execuție al funcției în sine.

Se întâmplă ca executarea unei funcții să dureze mai mult decât întârzierea. De exemplu, funcția este complexă și latența este mică. Sau funcția conține instrucțiuni de alertă / confirmare / prompt care blochează firul de execuție. În acest caz, încep lucruri interesante.

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

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

Un apel funcțional inițiat de setInterval este adăugat la coadă și apare imediat când devine posibil:

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

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

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

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

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

Există momente în care întârzierea reală este mai mare sau mai mică decât cea specificată. În general, nu este un fapt faptul că va exista cel puțin un fel de întârziere.

Repetarea setTimeout imbricat

În cazurile în care nu este necesară doar repetarea regulată, dar este necesară o întârziere între porniri, setTimeout este resetat 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.

<input type = "button" onclick = "clearTimeout (timer)" value = "(! LANG: Stop" > !} <script> var i = 1; var timer = setTimeout ( function run ()(alert (i ++); timer = setTimeout (run, 2000);), 2000);script>

Vor exista întârzieri fixe între rulări pe cronologia de execuție. Ilustrație pentru întârziere de 100 ms:

Întârziere minimă a temporizatorului

Temporizatorul browserului are cea mai mică latență posibilă. Acesta variază de la aproximativ zero la 4 ms în browserele moderne. La cei mai în vârstă, poate fi mai mare și poate atinge 15 ms.

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

Comportamentele setTimeout și setInterval cu latență zero sunt specifice browserului.

  1. În Opera, setTimeout (.., 0) este același cu setTimeout (.., 4). Se execută mai rar decât setTimeout (.., 2). Aceasta este o caracteristică a acestui browser.
  2. În Internet Explorer, un setInterval de întârziere zero (.., 0) nu va funcționa. Acest lucru se aplică în mod specific setInterval, adică setTimeout (.., 0) funcționează bine.

Frecvența de răspuns reală

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 (desktop, în primul rând) continuă să execute setTimeout / setInterval, chiar dacă fila este inactivă. În același timp, un număr dintre acestea (Chrome, FF, IE10) reduc frecvența minimă a temporizatorului, până la 1 dată pe secundă. Se pare că un temporizator va fi declanșat în fila „fundal”, dar rar.

Când funcționează cu baterie, într-un laptop - browserele pot, de asemenea, să scadă frecvența pentru a executa codul mai rar și a economisi energia bateriei. IE este faimos în special pentru acest lucru. Reducerea poate fi de până la mai multe ori, în funcție de setări. Dacă încărcarea procesorului este prea grea, este posibil ca JavaScript să nu poată procesa temporizatoarele la timp. Aceasta va sări peste unele dintre rulările setInterval.

Concluzie: ar trebui să fii ghidat de frecvența de 4 ms, dar nu ar trebui să te bazezi pe ea.

Trimiterea intervalelor către consolă Codul care numără intervalele dintre apeluri arată cam așa:

var timeMark = data nouă; setTimeout ( funcție go ()(var diff = new Date - timeMark; // imprimați o altă întârziere pe consolă în locul paginii consola .log (dif); // amintește-ți timpul de la sfârșit, // pentru a măsura întârzierea exact între apeluri timeMark = data nouă; setTimeout (go, 100); ), 100);

Trucul setTimeout (func, 0)

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

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

Ideea este că setTimeout nu execută niciodată o funcție imediat. El planifică doar implementarea acestuia. Dar interpretul JavaScript va începe să execute funcțiile planificate numai după executarea scriptului curent.

În mod standard, setTimeout nu poate executa oricum o funcție cu o întârziere de 0. După cum am spus mai devreme, de obicei întârzierea va fi de 4 ms. Dar principalul lucru aici este că executarea în orice caz va fi după executarea codului curent.

De exemplu:

var rezultat; funcție showResult ()(alertă (rezultat);) setTimeout (showResult, 0); rezultat = 2 * 2; // va imprima 4

Total

Metodele setInterval (func, delay) și setTimeout (func, delay) permit funcțiilor să fie rulate regulat / o dată după întârziere în milisecunde.

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

| | setInterval | setTimeout | || ----------- | ---------- | | Temporizare | Un apel este în desfășurare strict pe un temporizator. Dacă interpretul este ocupat, un apel intră în coadă. Timpul de execuție al funcției nu este luat în considerare, astfel încât intervalul de timp de la sfârșitul unei runde până la începutul alteia poate fi diferit. | Apelul recursiv la setTimeout este utilizat î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 ale browserului | Întârzierea 0 nu funcționează în IE | În Opera, latența zero este echivalentă cu 4 ms, alte întârzieri sunt tratate cu precizie, inclusiv 1ms, 2ms și 3ms non-standard. |

În programarea în limbaje de script, este necesar periodic să creați o pauză - să suspendați execuția programului pentru o vreme și apoi să continuați să lucrați. De exemplu, în scripturile VBS și PHP, sunt posibile următoarele metode:

VBS: wscript.sleep 1500 (opriți timp de 1,5 secunde)

PHP: sleep (10); (opriți-vă 10 secunde)

În timpul unor astfel de pauze, sistemul de execuție (PHP sau VBS) facand nimic... Un dezvoltator care încearcă să utilizeze intuitiv așa ceva în Javascript va fi surprins neplăcut. O eroare tipică la încercarea de a crea o pauză în Javascript arată astfel:

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

Crezi că atunci când, când treci prin buclă, vine să tragi următoarea cifră, setTimeout va opri sincer Javascript, va aștepta 0,9 secunde, va adăuga numărul necesar la sfârșitul câmpului de intrare și apoi va continua să lucreze. Dar, de fapt, nu este: setIntervalși setTimeoutîn Javascript, doar acțiunea (sau funcția) specificată între paranteze este întârziată. În exemplul nostru, se vor întâmpla următoarele:

  1. i = 1;
  2. amână adăugarea numărului „1” la câmpul de introducere cu 0,9 secunde;
  3. imediat după setarea acestei probleme, ciclul continuă: i = 2;
  4. amână adăugarea numărului "2" la câmpul de introducere cu 0,9 secunde;

Imediatînseamnă, de exemplu, 1 ms (adică incomensurabil de mic, comparativ cu 900 ms): ciclul își va efectua activitatea aproape instantaneu, creând mai multe sarcini în așteptare din același moment. 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 numere noi. Ciclul începe; totul îngheață timp de 0,9 s; și shirrr - toate numerele sunt împușcate la rând unul după altul.

Și cum, într-un astfel de caz, este corect să se aplice setTimeout? Este complicat. Trebuie să apelați funcția recursiv(din interiorul funcției, aceeași funcție), și astfel încât acest proces să nu fie infinit, setați condiția de oprire (de exemplu, valoarea numărului tipărit):

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

Și o altă variabilă eu va trebui 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ă nu folosiți setTimeout A setInterval(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"). Valoare + = ++ i if (i > = 9) clearInterval (window.timer1))

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

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

Iată un exemplu de pagină cu mai multe temporizatoare Javascript care rulează în același timp: setinterval.htm (funcțiile Javascript din fișierul setinterval.js). Funcționarea tuturor temporizatoarelor de pagină (cu excepția meniului) poate fi oprită apăsând tasta Esc. Toate cronometrele de exemplu se bazează pe „natural” (nu abstract i ++) numărătoare inversă - timp sau distanță. Toate „ceasurile” sunt special desincronizate (pentru claritate). Cronometrele bazate pe distanță sunt utilizate în „indicator” și în meniul derulant (derulant).

Meniu derulant

Meniul nostru extensibil este de fapt extras (de sub „antet”): există goluri între elemente pentru a vedea cum se extrage. În mod neașteptat, sa dovedit că nu putem face o ieșire la fel de lină pentru listele de diferite lungimi - probabil datorită 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 la o rată mai rapidă, mai scurte - la o rată mai mică. S-ar părea că acest lucru poate fi implementat astfel:

  1. Am setat timpul total de „plecare”, de exemplu, în 200 ms.
  2. Dacă lista derulantă are o înălțime de 20 px, este evident că o putem deplasa în jos cu un pixel la un moment de 10 ms - și apoi în 200 ms va apărea întreaga listă.
  3. Dacă meniul derulant are o înălțime de 40 px, pentru a se potrivi în același timp, trebuie să-l mutăm în jos cu un pixel la un moment dat în 5 ms.

Conform acestei logici, dacă lista derulantă are o înălțime de 200 px, trebuie să o mutăm în jos cu un pixel la un moment dat în 1 ms. Dar această viteză nu funcționează pe computerul nostru - browserul pur și simplu nu are timp să atragă noua poziție a listei într-o milisecundă. Da. Javascript are timp să numere (ce este de numărat?), Iar browserul (Firefox) nu are timp să se afișeze. O situație tipică pentru web.

Prin urmare, este posibil să egalizăm mai mult sau mai puțin timpul de ieșire din meniu numai cu ajutorul cârjelor și încă nu este clar cum va funcționa acest lucru pe un computer mai rapid. Dar trebuie să ne bazăm pe cel mai lent, nu? Algoritmul (fără a lua în considerare viteza computerului) se dovedește a fi ceva de genul acesta:

  1. Am stabilit timpul total de plată a listei: timp = 224 (ms).
  2. Am stabilit timpul minim pentru un interval din ciclu: întârziere = 3 (ms).
  3. Setați pasul minim pentru mutarea listei: offset = 1 (px).
  4. Modificăm toate acestea în funcție de înălțimea listei: 1) creștem timpul de întârziere (interval) în proporție inversă cu înălțimea și în proporție directă cu timpul total de timp (la o înălțime de 224, coeficientul este 1); 2) dacă înălțimea este mai mare de 40 px, creșteți pasul minim proporțional cu înălțimea. Constanta "40" este obținută empiric pentru cel mai lent computer. Testele pe un computer Pentium 4 CPU 2,53GHz au arătat exact același număr - 40. În caz contrar, temporizatoarele devin nebunești, listele sunt în afara pasului.

Acum listele se desfășoară mai mult sau mai puțin. Pentru un timp mai mult sau mai puțin similar. Pe pagina setinterval.htm.

Și iată mustața Bru:

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 scoate listele imbricate din meniu, este, după cum puteți vedea, foarte simplă. Rămâne doar să-l rulați cu ceva de genul:

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

Ei bine, înainte de a începe, calculați toate aceste maxtop și offset și, de asemenea, puneți lista în poziția mintop. Ce face funcția „preliminară” diapozitiv () 40 de linii în dimensiune. Și toate împreună - în fișierul setinterval.js. Da, iar această porcărie nu va funcționa fără o foaie de stil inclusă.