SetTimeOut i SetInterval, što je bolje koristiti u JavaScriptu? O tome kako JavaScript mjerači vremena rade Jquery interval za izvršavanje funkcije

💖 Sviđa li vam se? Podijelite vezu sa svojim prijateljima

JavaScript timeout izvorna je javascript funkcija koja izvršava dio koda nakon određenog vremenskog kašnjenja (u milisekundama). Ovo može biti korisno kada trebate prikazati skočni prozor nakon što je korisnik proveo neko vrijeme na vašoj stranici. Ili želite da efekt kada prijeđete iznad elementa počne tek nakon što prođe neko vrijeme? Na taj način možete izbjeći nenamjerno pokretanje efekta ako je korisnik slučajno priješao pokazivačem iznad njega.

Jednostavan primjer setTimeout

Da biste demonstrirali kako ova značajka radi, predlažem da pogledate sljedeću demonstraciju u kojoj se skočni prozor pojavljuje dvije sekunde nakon klika na gumb.

Pogledaj demo

Sintaksa

MDN dokumentacija pruža sljedeću sintaksu za setTimeout:

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

  • timeoutID – numerički ID koji se može koristiti u kombinaciji s clearTimeout() za onemogućavanje mjerača vremena;
  • func – funkcija koju treba izvršiti;
  • kod ( u alternativnoj sintaksi) – linija koda koju treba izvršiti;
  • odgoda – trajanje odgode u milisekundama nakon koje će se funkcija pokrenuti. Zadana vrijednost je 0.

setTimeout u odnosu na window.setTimeout

Gornja sintaksa koristi window.setTimeout. Zašto?

Zapravo, setTimeout i window.setTimeout su praktički iste funkcije. Jedina razlika je u tome što u drugom izrazu koristimo metodu setTimeout kao svojstvo globalnog objekta prozora.

Osobno, mislim da ovo samo čini kod puno kompliciranijim. Ako bismo definirali alternativu JavaScript metoda timeout , koji bi se mogli pronaći i vratiti po redoslijedu prioriteta, naišli bismo na još više problema.

U ovaj priručnik Ne želim se petljati s objektom prozora, ali općenito, na vama je koju ćete sintaksu koristiti.

Primjeri korištenja

Ovo bi mogao biti naziv funkcije:

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

Varijabla koja se odnosi na funkciju:

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

Ili anonimna funkcija:

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

  • Takav se kod slabo razumije i stoga će ga biti teško modernizirati ili otkloniti pogreške;
  • Uključuje korištenje metode eval(), koja bi mogla biti potencijalna ranjivost;
  • Ova metoda je sporija od drugih jer zahtijeva pokretanje JavaScript tumač.

Također imajte na umu da koristimo JavaScript metodu upozorenja o isteku vremena za testiranje koda.

Prosljeđivanje parametara u setTimout

U prvom ( osim toga, cross-browser), prosljeđujemo parametre funkciji povratnog poziva koja se izvodi pomoću setTimeout-a.

U sljedećem primjeru izvlačimo nasumični pozdrav iz niza pozdrava i prosljeđujemo ga kao parametar funkciji greet(), koju izvršava setTimeout s odgodom od 1 sekunde:

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

Pogledaj demo

Alternativna metoda

U sintaksi danoj na početku članka, postoji još jedna metoda kojom možete proslijediti parametre funkciji povratnog poziva koja se izvršava prema vremenskom ograničenju JavaScripta. Ova metoda podrazumijeva izlaz svih parametara nakon kašnjenja.

Na temelju prethodnog primjera dobivamo:

setTimeout(greet, 1000, randomGreeting);

Ova metoda neće raditi u IE 9 i nižim, gdje se proslijeđeni parametri tretiraju kao nedefinirani. Ali za rješavanje ovog problema MDN ima poseban polifil.

Povezani problemi i "ovo"

Kod koji izvodi setTimeout izvodi se odvojeno od funkcije koja ga je pozvala. Zbog toga se suočavamo s određenim problemima čije se rješenje može iskoristiti ključna riječ ovaj.

var person = ( firstName: "Jim", uvod: function())( console.log("Hi, I"m " + this.firstName); ) ); person.introduce(); // Izlazi: Bok, I " m Jim setTimeout(person.introduce, 50); // Izlazi: Bok, ja sam nedefiniran

Razlog za ovaj izlaz je taj što u prvom primjeru ukazuje na objekt osobe, au drugom primjeru pokazuje na globalni objekt prozora, koji nema svojstvo firstName.

Da biste se riješili ove nedosljednosti, možete koristiti nekoliko metoda:

Prisilno postavite ovo

To se može učiniti pomoću bind(), metode koja stvara nova značajka, koji kada se pozove koristi određenu vrijednost kao vrijednost ovog ključa. U našem slučaju navedena osoba prigovara. Ovo nam u konačnici daje:

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

Napomena: metoda vezanja uvedena je u ECMAScript 5, što znači da će raditi samo u modernim preglednicima. U drugima, kada ga koristite, dobit ćete pogrešku prilikom izvođenja JavaScript "pogreška isteka vremena funkcije".

Koristi knjižnicu

Mnoge biblioteke uključuju ugrađene funkcije potrebne za rješavanje ovog problema. Na primjer, metoda jQuery.proxy(). Uzima funkciju i vraća novu koja će uvijek koristiti određeni kontekst. U našem slučaju, kontekst će biti:

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

Pogledaj demo

Onemogućivanje mjerača vremena

Povratna vrijednost setTimeouta je numerički ID koji se može koristiti za onemogućavanje mjerača vremena pomoću funkcije clearTimeout():

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

Pogledajmo ga na djelu. U sljedećem primjeru, ako kliknete na gumb " Započni odbrojavanje“, počet će odbrojavanje. Nakon završetka, mačići će dobiti svoje. Ali ako pritisnete gumb Zaustavi odbrojavanje", vremensko ograničenje JavaScripta bit će zaustavljeno i poništeno.

Pogledajte primjer

Sažmimo to

setTimeout je asinkrona funkcija, što znači da rezultirajući poziv ove funkcije ide u red čekanja i bit će izvršen tek nakon što se završe sve druge radnje na stogu. Ne može se izvoditi istovremeno s drugim funkcijama ili zasebnom niti.

Izuzetno je važno razumjeti kako rade JavaScript mjerači vremena. Često njihovo ponašanje ne odgovara našem intuitivnom razumijevanju višenitnosti, a to je zbog činjenice da se u stvarnosti izvršavaju u jednoj niti. Pogledajmo četiri funkcije pomoću kojih možemo upravljati mjeračima vremena:

  • var id = setTimeout(fn, kašnjenje); - Stvara jednostavan mjerač vremena koji će pozvati zadanu funkciju nakon zadane odgode. Funkcija vraća jedinstveni ID s kojim se tajmer može pauzirati.
  • var id = setInterval(fn, kašnjenje); - Slično setTimeoutu, ali kontinuirano poziva funkciju u određenom intervalu (dok se ne zaustavi).
  • clearInterval(id);, clearTimeout(id); - Prihvaća ID tajmera (koji vraća jedna od gore opisanih funkcija) i zaustavlja izvršenje povratnog poziva"a.
Glavna ideja koju treba uzeti u obzir je da točnost razdoblja odgode timera nije zajamčena. Za početak, preglednik izvršava sve asinkrone JavaScript događaje u jednoj niti (kao što su klikovi mišem ili tajmeri) i to samo u trenutku kada je taj događaj na redu. To najbolje pokazuje sljedeći dijagram:

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

JavaScript može izvršiti samo jedan dio koda (zbog jednonitne prirode izvršavanja), od kojih svaki blokira izvršavanje drugih asinkronih događaja. To znači da kada se dogodi asinkroni događaj (kao što je klik mišem, poziv mjerača vremena ili završetak XMLHttp zahtjeva), on se dodaje u red čekanja i izvršava kasnije (implementacija ovisi o pregledniku, naravno, ali složimo se da nazovite to "red čekanja") .

Za početak, zamislimo da se dva mjerača vremena pokreću unutar JavaScript bloka: setTimeout s odgodom od 10 ms i setInterval s istom odgodom. Ovisno o tome kada se mjerač vremena pokrene, aktivirat će se u trenutku kada još nismo dovršili prvi blok koda. Međutim, imajte na umu da se ne aktivira odmah (to nije moguće zbog jednostrukog navoja). Umjesto toga, odgođena funkcija stavlja se u red čekanja i izvršava u sljedećem dostupnom trenutku.

Također, tijekom izvođenja prvog JavaScript bloka dolazi do klika mišem. Rukovatelj za ovaj asinkroni događaj (a on je asinkroni jer ga ne možemo predvidjeti) ne može se izvršiti izravno u ovom trenutku, tako da također završava u redu čekanja, poput mjerača vremena.

Nakon što je prvi blok JavaScript koda izvršen, preglednik postavlja pitanje: "Što čeka na izvršenje?" U ovom slučaju rukovatelj klikom miša i mjerač vremena su u stanju čekanja. Preglednik odabire jedan od njih (obavljač klikova) i izvršava ga. Mjerač vremena će čekati sljedeći raspoloživi dio vremena u redu čekanja za izvršavanje.

Imajte na umu da dok se rukovatelj klikom miša izvršava, aktivira se prvi interval povratnog poziva. Baš kao i tajmer-callback, bit će stavljen u red čekanja. Međutim, imajte na umu da će interval biti uklonjen iz reda čekanja kada se ponovno aktivira (dok je pokrenut povratni poziv timera). Kad bi se svaki interval-callback" stavio na čekanje dok se izvodi veliki dio koda, to bi rezultiralo hrpom funkcija koje čekaju da budu pozvane, bez razdoblja odgode između njih da završe svoje izvršenje. Umjesto toga, preglednici imaju tendenciju čekati dok nema preostalo je više funkcija u redu čekanja prije dodavanja još jedne u red čekanja.

Dakle, možemo promatrati slučaj kada se treće aktiviranje povratnog poziva intervala poklapa s trenutkom kada je već izvršen. Ovo ilustrira važnu točku: intervalima nije važno što se trenutno izvodi, oni će biti dodani u red čekanja bez obzira na razdoblje odgode između izvršenja.

Konačno, nakon završetka drugog intervala povratnog poziva, vidjet ćemo da nema više ništa što bi JavaScript mehanizam mogao izvršiti. To znači da preglednik ponovno čeka na pojavu novih asinkronih događaja. To će se dogoditi na oznaci od 50 ms, gdje će ponovno raditi intervalni povratni poziv. U ovom trenutku neće biti ničega što bi ga blokiralo, pa će odmah raditi.

Pogledajmo primjer koji lijepo ilustrira razliku između setTimeout i setInterval.
setTimeout(function())( /* Neki dugi blok koda... */ setTimeout(arguments.callee, 10); ), 10); setInterval(function())( /* Neki dugi blok koda... */ ), 10);
Ove dvije opcije su na prvi pogled jednake, ali u stvarnosti nisu. Kod koji koristi setTimeout uvijek će imati odgodu od najmanje 10 ms nakon prethodnog poziva (može biti više, ali nikad manje), dok će kod koji koristi setInterval težiti pozivanju svakih 10 ms, bez obzira na to kada se dogodio prethodni poziv.

Rezimirajmo sve gore rečeno:
- JavaScript motori koriste okruženje s jednom niti, pretvarajući asinkrone događaje u red čekanja na izvršenje,
- Funkcije setTimeout i setInterval izvršavaju se bitno drugačije u asinkronom kodu,
- Ako se mjerač vremena ne može izvršiti u ovaj trenutak, odgodit će se do sljedeće točke izvršenja (koja će biti dulja od željene odgode),
- Intervali (setInterval) mogu se izvršavati jedan za drugim bez odgode ako njihovo izvršenje traje dulje od navedenog odgode.

Sve je ovo izuzetno važna informacija za razvoj. Poznavanje načina rada JavaScript mehanizma, posebno s puno asinkronih događaja (što se često događa), postavlja izvrsne temelje za izradu naprednih aplikacija.

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

Gotovo sve implementacije JavaScripta imaju interni programator vremena koji vam omogućuje da zakažete pozivanje funkcije nakon određenog vremenskog razdoblja.

Konkretno, ova je značajka podržana u preglednicima i na poslužitelju Node.JS.

setTimeout

Sintaksa:

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

Mogućnosti:

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

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

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

Ako je prvi argument niz, tada tumač stvara anonimnu funkciju iz tog niza.

Odnosno, ovaj unos radi potpuno isto:

SetTimeout("upozorenje("Pozdrav")" , 1000 );

Umjesto toga koristite anonimne funkcije:

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

Parametri za funkciju i kontekst

U svim modernim preglednicima, uključujući IE10, setTimeout vam omogućuje određivanje parametara funkcije.

Primjer ispod ispisat će "Zdravo, ja sam Vasya" svugdje osim IE9-:

funkcija pozdravi (tko)( alert("Bok, ja sam " + tko); ) setTimeout(sayBok, 1000, "Vasja");

...Međutim, u većini slučajeva trebamo podršku starog IE-a, a on vam ne dopušta navođenje argumenata. Stoga, kako bi ih prenijeli, oni upakuju poziv u anonimnu funkciju:

funkcija pozdravi (tko)( alert("Bok, ja sam " + tko); ) setTimeout( funkcija()( reciBok("Vasya")), 1000);

Pozivanje setTimeout ne prosljeđuje ovaj kontekst.

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

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

korisnik funkcije (id) funkcija()( upozorenje(ovaj .id); ); ) var user = new User(12345); setTimeout(user.sayHi, 1000); // očekuje se 12345, ali će ispisati "undefined"

Budući da će setTimeout pokrenuti funkciju user.sayHi u globalnom kontekstu, neće imati pristup objektu putem ovog.

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

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

Srećom, ovaj se problem također lako rješava stvaranjem posredne funkcije:

korisnik funkcije (id)(ovo .id = id; ovo .sayHi = funkcija()( upozorenje(ovaj .id); ); ) var korisnik = novi korisnik(12345); setTimeout( funkcija()(korisnik.sayHi();), 1000);

Funkcija omotača koristi se za prosljeđivanje argumenata u različitim preglednicima i očuvanje konteksta izvršenja.

Otkazivanje ovrhe

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

Sintaksa:

ClearTimeout(timerId)

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

var timerId = setTimeout( funkcija()(upozorenje(1)), 1000); clearTimeout(timerId);

setInterval

Metoda setInterval ima sintaksu sličnu setTimeout.

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

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

ClearInterval(timerId)

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

<tip unosa ="button" onclick ="clearInterval(timer)" value ="Stop" > !} <skripta > var i = 1; var timer = setInterval( funkcija()( alert(i++) ), 2000.);skripta >

Pozivi u redu čekanja i preklapanje u setIntervalu

Poziv setInterval(function, delay) uzrokuje izvršavanje funkcije u navedenom vremenskom intervalu. Ali tu postoji jedna suptilnost.

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

Na primjer, uzmimo setInterval(function() ( func(i++)), 100) . Izvršava func svakih 100 ms, povećavajući brojač svaki put.

Na slici ispod, crveni blok je vrijeme izvršenja funkcije func. Interblock vrijeme je vrijeme između pokretanja funkcije i manje je od postavljene odgode!

Odnosno, preglednik uredno inicira pokretanje funkcije svakih 100ms, ne uzimajući u obzir vrijeme izvršenja same funkcije.

Dešava se da izvršenje funkcije traje dulje od odgode. Na primjer, funkcija je složena, ali je kašnjenje malo. Ili funkcija sadrži izjave upozorenja / potvrde / upita koje blokiraju nit izvršavanja. Ovdje stvari počinju biti zanimljive.

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

Slika u nastavku ilustrira što se događa s funkcijom za čije je izvršavanje potrebno puno vremena.

Poziv funkcije koji pokreće setInterval dodaje se u red i pojavljuje se odmah kada je to moguće:

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

Izvršenje se ne stavlja na čekanje više od jednom.

Ako je za izvršenje funkcije potrebno dulje od nekoliko zakazanih izvršavanja, ona će se ipak jednom staviti u red čekanja. Dakle, nema "nagomilavanja" lansiranja.

Na slici ispod, setInterval pokušava izvršiti funkciju za 200 ms i stavlja poziv u red čekanja. Na 300ms i 400ms mjerač vremena se ponovno budi, ali ništa se ne događa.

Pozivanje setInterval(function, delay) ne jamči stvarno kašnjenje između izvršavanja.

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

Ponavljanje ugniježđenog setTimeout-a

U slučajevima kada vam nije potrebno samo redovito ponavljanje, već i obvezna odgoda između pokretanja, koristite ponovna instalacija setTimeout svaki put kada se funkcija izvrši.

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

<tip unosa ="button" onclick ="clearTimeout(timer)" value ="Stop" > !} <skripta > var i = 1; var timer = setTimeout( funkcija run()( alert(i++); timer = setTimeout(run, 2000); ), 2000);skripta >

Vremenska traka izvršenja imat će fiksna kašnjenja između pokretanja. Ilustracija za odgodu od 100 ms:

Minimalna odgoda mjerača vremena

Mjerač vremena preglednika ima najnižu moguću latenciju. U modernim preglednicima varira od približno nule do 4 ms. Kod starijih može biti dulje i doseći 15 ms.

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

Ponašanje setTimeouta i setIntervala bez kašnjenja je specifično za preglednik.

  1. U Operi, setTimeout(.., 0) je isto što i setTimeout(.., 4) . Izvršava se rjeđe nego setTimeout(.. ,2). Ovo je značajka ovog preglednika.
  2. U Internet Explorer, nulta odgoda setInterval(.., 0) neće raditi. Ovo se posebno odnosi na setInterval, tj. setTimeout(.., 0) radi dobro.

Stvarna frekvencija okidača

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

Većina preglednika (prvenstveno onih za stolna računala) nastavljaju izvršavati setTimeout / setInterval čak i ako je kartica neaktivna. U isto vrijeme, neki od njih (Chrome, FF, IE10) smanjuju minimalnu frekvenciju mjerača vremena na 1 put u sekundi. Ispostavilo se da će mjerač vremena raditi u kartici "pozadina", ali rijetko.

Kada na prijenosnom računalu rade na baterijsko napajanje, preglednici također mogu smanjiti učestalost kako bi rjeđe izvršavali kod i štedjeli bateriju. IE je posebno poznat po tome. Smanjenje može doseći nekoliko puta, ovisno o postavkama. Ako je opterećenje CPU-a previsoko, JavaScript možda neće moći obraditi tajmere na vrijeme. Ovo će preskočiti neka pokretanja setIntervala.

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

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

var timeMark = novi datum; setTimeout( funkcija go()( var diff = novi datum - oznaka vremena; // izbaci sljedeće kašnjenje na konzolu umjesto na stranicu konzola .log(diff); // zapamti vrijeme na samom kraju, // za mjerenje kašnjenja između poziva timeMark = novi datum; setTimeout(kreni, 100); ), 100 );

Trik je setTimeout(func, 0)

Ovaj trik je vrijedan ulaska u anale JavaScript hakova.

Funkcija je omotana u setTimeout(func, 0) ako je želite pokrenuti nakon završetka trenutne skripte.

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

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

Na primjer:

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

Ukupno

Metode setInterval(func, delay) i setTimeout(func, delay) omogućuju vam pokretanje func redovito/jednom svake milisekunde kašnjenja.

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

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

U programiranju skriptni jezici S vremena na vrijeme potrebno je napraviti pauzu - nakratko zaustaviti izvođenje programa, a zatim nastaviti s radom. Na primjer, u VBS i PHP skriptama moguće su sljedeće metode:

VBS: wscript.sleep 1500 (zaustavi se na 1,5 sekundi)

PHP: spavanje(10); (zaustavite 10 sekundi)

Tijekom takvih pauza, runtime sustav (PHP ili VBS) ne radeći ništa. Programer koji pokuša intuitivno koristiti nešto slično u Javascriptu bit će neugodno iznenađen. Uobičajena greška kada pokušavate stvoriti pauzu u Javascriptu, to izgleda ovako:

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

Mislite li da kada tijekom ciklusa dođe red na izvlačenje sljedećeg broja, vaš setTimeout pošteno će prestati Javascript rad, pričekat će 0,9 sekundi, dodati traženi broj na kraj polja za unos i zatim nastaviti s radom. Ali zapravo nije: setInterval I setTimeout U Javascriptu se odgađa samo radnja (ili funkcija) navedena u zagradama. U našem primjeru dogodit će se sljedeće:

  1. i = 1;
  2. odgoditi dodavanje broja "1" u polje za unos za 0,9 sekundi;
  3. odmah Nakon postavljanja ovog problema, ciklus ide dalje: i=2;
  4. odgoditi dodavanje broja "2" u polje za unos za 0,9 sekundi;

Odmah znači, na primjer, 1 ms (tj. neproporcionalno malo u usporedbi s 900 ms): petlja će obaviti svoj posao gotovo trenutno, stvarajući nekoliko odgođenih zadataka iz iste vremenske točke. To znači da će svi zadaci "crtanja" na čekanju biti završeni gotovo u isto vrijeme, bez pauza između dodavanja novih brojeva. Ciklus počinje; sve se zamrzava 0,9 s; i shirr - svi brojevi se nižu jedan za drugim.

Kako ga ispravno koristiti u takvom slučaju? setTimeout? Komplicirano je. Morat ćete pozvati funkciju rekurzivno(iznutar funkcije ista funkcija), a kako ovaj proces ne bi bio beskrajan, postavite uvjet zaustavljanja (npr. veličinu broja koji se ispisuje):

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

I još jedna varijabla ja morat ćete inicijalizirati izvan funkcije - na primjer, ovako:

Sada sve radi kako treba (smanjili smo vrijeme kašnjenja s 0,9 s na 0,4 s). Ali za takve zadatke logičnije je ne koristiti setTimeout A setInterval(iako će to zahtijevati dvije funkcije):

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

Značajka Javascirpt metode setIntervalčinjenica da ne prolazi "sam od sebe", mora se zaustaviti posebnom metodom clearInterval. A kako bi bilo jasno što točno zaustaviti, zadatku za odgođenu radnju dodjeljuje se poseban identifikator - mjerač vremena: window.timer1 = window.setInterval(...) .

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

Ovdje je primjer stranice s nekoliko Javascript timera koji rade istovremeno: setinterval.htm (Javascript funkcionira u datoteci setinterval.js). Svi mjerači vremena stranica (osim izbornika) mogu se zaustaviti tipkom Esc. Svi primjeri mjerača vremena oslanjaju se na "prirodno" (a ne na apstraktno) i++) odbrojavanje – vrijeme ili udaljenost. Svi "satovi" su posebno desinkronizirani (radi jasnoće). Tajmeri ovisni o udaljenosti koriste se u "indikatoru" iu padajućem ("izvlačnom") izborniku.

Padajući izbornik

Naš klizni izbornik zapravo je klizni (ispod "zaglavlja"): posebno su ostavljeni razmaci između elemenata tako da možete vidjeti kako klizi van. Neočekivano se pokazalo da ne možemo napraviti jednako glatke izlaze za popise različitih duljina - vjerojatno zbog niske performanse računala ( AMD Athlon 999 MHz).

Sasvim je očito da je za ljepotu i sklad potrebno da se popisi različitih stavki jelovnika pojavljuju u isto vrijeme. Odnosno, dulji popisi trebali bi ispasti s više velika brzina, kraće - manjom brzinom. Čini se da bi se to moglo implementirati ovako:

  1. Postavljamo ukupno vrijeme "odlaska", na primjer, 200 ms.
  2. Ako padajući popis ima visinu od 20 px, očito je da ga možemo pomaknuti jedan piksel prema dolje u intervalu od 10 ms - i tada će za 200 ms izaći cijeli popis.
  3. Ako je padajući izbornik visok 40 piksela, da bismo stali u isto vrijeme, moramo ga pomaknuti za jedan piksel prema dolje svakih 5 ms.

Po ovoj logici, ako je padajući popis visok 200 piksela, trebali bismo ga pomaknuti za jedan piksel prema dolje svakih 1 ms. Ali takva brzina ne radi na našem računalu - preglednik jednostavno nema vremena iscrtati novu poziciju popisa u jednoj milisekundi. Da. Javascript uspijeva brojati (što se ima brojati?), ali preglednik (Firefox) nema vremena za prikaz. Tipična situacija za web.

Dakle, koliko-toliko je moguće ujednačiti vrijeme odlaska izbornika samo uz pomoć štaka, a još je nejasno kako će to funkcionirati za više brzo računalo. Ali treba računati na najsporijeg, zar ne? Algoritam (bez uzimanja u obzir brzine računala) ispada ovako:

  1. Postavite ukupno vrijeme za provjeru popisa: vrijeme = 224 (ms).
  2. Postavljamo minimalno vrijeme za jedan interval u ciklusu: kašnjenje = 3 (ms).
  3. Postavite minimalni korak za pomicanje liste: pomak = 1 (px).
  4. Sve to mijenjamo ovisno o visini liste: 1) povećavamo vrijeme kašnjenja (intervala) obrnuto proporcionalno visini i izravno proporcionalno ukupnom vremenskom vremenu (na visini 224 koeficijent je 1); 2) ako je visina veća od 40 px, povećajte minimalni korak proporcionalno visini. Konstanta "40" dobivena je eksperimentalno za najsporije računalo. Testovi na računalu s procesorom Pentium 4 2,53 GHz otkrili su točno isti broj - 40. U suprotnom, mjerači vremena ne rade ispravno, popisi se poremete.

Sada manje-više izlaze liste. Za više-manje slično vrijeme. Na stranici setinterval.htm.

I dolazi Bruce:

Funkcija slide_do(obj, maxtop, offset) ( if (getTopLeft(obj).top< maxtop) { obj.style.top = getTopLeft(obj).top + offset } else { if (obj && obj.timer1) { clearInterval(obj.timer1) obj.timer1 = null } } }

Sama funkcija koja izbacuje ugniježđene liste iz izbornika je, kao što vidimo, vrlo jednostavna. Sve što preostaje je pokrenuti ga s nečim poput ovog retka:

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

Pa, prije početka, samo izračunajte sve te maxtop i offset, a također postavite listu na mintop poziciju. Što radi "preliminarna" funkcija? slajd() Veličina 40 redaka. I sve zajedno – u datoteci setinterval.js. Da, i ovo sranje uopće neće raditi bez uključene datoteke stilova

  • Iz:
  • Registriran: 2014.07.08
  • Postovi: 3,896
  • Sviđa mi se: 497

Tema: SetTimeOut i SetInterval, što je bolje koristiti u JavaScriptu?

Za pokretanje koda više puta u pravilnim intervalima, upotrijebite ovu funkciju setInterval. Međutim, ima niz nedostataka, uglavnom drugačije ponašanje u različitim preglednicima.

Prva razlika je razlika u vremenu u kojem je mjerač vremena postavljen za sljedeće pokretanje. Napravimo mali test: izmjerit ćemo koliko je vremena prošlo od početka prethodnog pokretanja i od njegovog završetka.

var d1 = novi datum(), d2 = novi datum(); setInterval(function() ( var d = new Date(); document.body.innerHTML += (d - d1) + " " + (d - d2) + "
"; // Stavite oznaku na početak funkcije d1 = new Date(); while (new Date() - d1< 200); // ничего не делаем 200 миллисекунд // И в конце функции d2 = new Date(); }, 1000);

Izlaz će biti informativan počevši od drugog retka.

U Firefoxu, Operi, Safariju i Chromeu situacija će biti slična: prvi broj će biti približno jednak 1000, drugi - 200 manji. Jedina će razlika biti u širenju vrijednosti. Najmanja razlika je u Chromeu i Operi.

2 Odgovori od PunBB (uredio PunBB 2017.08.06. 16:45)

  • Iz: Moskva, Sovkhoznay 3, apt. 98
  • Registriran: 2014.07.08
  • Postovi: 3,896
  • Sviđa mi se: 497

Još jedna razlika koja je manje uočljiva i teže ju je reproducirati, ali ponekad može uzrokovati mnogo problema, jest otpornost na promjene vremena sustava. Ako pokrenete sljedeći test

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

I nakon pokretanja, vratite sistemsko vrijeme minutu unatrag, a zatim na Firefox preglednici i Safari, promjena broja će se zaustaviti, a nakon minute će ponovno započeti. Naravno, ručno prevođenje sistemskog vremena iznimno je rijetka situacija, ali mnogi su sustavi konfigurirani za automatsku sinkronizaciju vremena s poslužiteljima na Internetu, tako da se u nekim situacijama ovaj faktor ne može zanemariti.

Još jedan mali nedostatak funkcije setInterval je taj što, da biste mogli zaustaviti njezino djelovanje, morate negdje zapamtiti njegov identifikator, što nije uvijek zgodno.

3 Odgovori od PunBB

  • Iz: Moskva, Sovkhoznay 3, apt. 98
  • Registriran: 2014.07.08
  • Postovi: 3,896
  • Sviđa mi se: 497

Re: SetTimeOut i SetInterval, što je bolje koristiti u JavaScriptu?

Da biste se riješili navedenih nedostataka setIntervala, možete koristiti višestruki setTimeout.

Važna alternativa setIntervalu je rekurzivni setTimeout:

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

U gornjem kodu, sljedeće izvršenje zakazano je odmah nakon završetka prethodnog.

Rekurzivni setTimeout je fleksibilnija metoda mjerenja vremena nego setInterval, budući da se vrijeme do sljedećeg izvršenja može drugačije rasporediti, ovisno o rezultatima trenutnog.

Na primjer, imamo uslugu koja provjerava poslužitelj za nove podatke svakih 5 sekundi. Ako je poslužitelj preopterećen, možete povećati interval prozivanja na 10, 20, 60 sekundi... I onda ga vratiti kada se sve vrati u normalu.

Ako redovito pokrećemo CPU-intenzivne zadatke, tada možemo procijeniti vrijeme utrošeno na njihovo izvršenje i planirati sljedeće pokretanje ranije ili kasnije.

4 Odgovori od PunBB

  • Iz: Moskva, Sovkhoznay 3, apt. 98
  • Registriran: 2014.07.08
  • Postovi: 3,896
  • Sviđa mi se: 497

Re: SetTimeOut i SetInterval, što je bolje koristiti u JavaScriptu?

Rekurzivni setTimeout jamči pauzu između poziva, setInterval ne.

Usporedimo dva koda. Prvi koristi setInterval:

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

Drugi koristi rekurzivni setTimeout:

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

Uz setInterval, interni mjerač vremena aktivirat će se točno svakih 100 ms i pozvati funkciju (i):

Prava pauza između func poziva sa setInterval je manja nego što je navedeno u kodu!

To je prirodno, jer se vrijeme rada funkcije ni na koji način ne uzima u obzir, ono "pojede" dio intervala.

Također je moguće da se func pokazao složenijim nego što smo očekivali i da je za izvršenje trebalo više od 100 ms.

U ovom slučaju, tumač će čekati da funkcija završi, zatim provjeriti mjerač vremena i, ako je vrijeme za pozivanje setIntervala već došlo (ili prošlo), tada će se sljedeći poziv dogoditi odmah.

Ako funkcija radi dulje od pauze setInterval, tada će se pozivi dogoditi bez ikakvih prekida.

5 Odgovori od sempai

  • Iz: Jeruzalem
  • Registriran: 2015.06.02
  • Postovi: 958
  • Sviđa mi se: 274

Re: SetTimeOut i SetInterval, što je bolje koristiti u JavaScriptu?

Sve ovisi o zadatku koji se radi. U početku se SetTimeOut koristi za jednokratno pokretanje mjerača vremena, a SetInterval za pokretanje petlje. Ali obje funkcije se mogu koristiti za cikličko pokretanje skripti; ako ih, na primjer, pokrenete rekurzivno u funkciji SetTimeOut, tada će djelovati gotovo slično kao SetInterval.

Nedostatak SetIntervala trenutno je što ne uzima u obzir vrijeme izvršenja same skripte (funkcije), a ako ga npr. koristite za teške upite, tada će vrijeme intervala biti značajno smanjeno, a mogu se razlikovati u različitim preglednicima.

Ali opet, ako je funkcija ili zahtjev minimiziran, tada krajnji korisnik vjerojatno neće osjetiti razliku.
Stoga, što koristiti, svatko odlučuje za sebe.



reci prijateljima
Pročitajte također