Përsëritni veprimet në një interval kohor të caktuar javascript. Shembuj të funksionit jQuery setTimeout()

Shtëpi / teknologjitë

Metoda setInterval(), e ofruar në ndërfaqet Window dhe Worker, thërret në mënyrë të përsëritur një funksion ose ekzekuton një copë kodi, me një vonesë kohore fikse ndërmjet çdo thirrjeje.

Ai kthen një ID intervali që identifikon në mënyrë unike intervalin, kështu që ju mund ta hiqni atë më vonë duke thirrur clearInterval() . Kjo metodë përcaktohet nga miksina WindowOrWorkerGlobalScope. Sintaksë = var intervalID fushëveprimi .setInterval(, func, [vonesë, arg1, ...]); Sintaksë = var intervalID fushëveprimi arg2, func kodi ); Parametrat funksionojnë Një funksion që duhet të ekzekutohet çdo milisekonda vonesë. Funksionit nuk i jepet asnjë argument dhe nuk pritet asnjë vlerë e kthimit. kodi Një sintaksë opsionale ju lejon të përfshini një varg në vend të një funksioni, i cili përpilohet dhe ekzekutohet çdo milisekonda vonese. Kjo sintaksë është .setInterval( nuk rekomandohet

për të njëjtat arsye që e bëjnë përdorimin e eval() një rrezik sigurie. vonesë Koha, në milisekonda (të mijëta e sekondës), kohëmatësi duhet të vonojë ndërmjet ekzekutimeve të funksionit ose kodit të specifikuar. Shihni më poshtë për detaje mbi gamën e lejuar të vlerave të vonesës. arg1, ..., argN Opsionale Argumente shtesë që kalohen në funksionin e specifikuar nga

sapo të skadojë kohëmatësi.

Shënim: Kalimi i argumenteve shtesë te setInterval() në sintaksën e parë nuk funksionon

Internet Explorer

9 dhe më herët. Nëse dëshironi të aktivizoni këtë funksion në atë shfletues, duhet të përdorni një polifill (shih seksionin).

Vlera e kthimit

IntervalID-i i kthyer është një vlerë numerike, jo zero, e cila identifikon kohëmatësin e krijuar nga thirrja në setInterval(); kjo vlerë mund të kalohet për të anuluar afatin.

Var intervalID = window.setInterval(myCallback, 500, "Parameter 1", "Parameter 2"); funksioni myCallback(a, b) ( // Kodi juaj këtu // Parametrat janë thjesht opsionale. console.log(a); console.log(b); )

Shembulli 2: Alternimi i dy ngjyrave

Shembulli i mëposhtëm thërret funksionin flashtext() një herë në sekondë derisa të shtypet butoni Stop.

Shembull setInterval/clearInterval var nIntervId;

funksioni changeColor() ( nIntervId = setInterval(flashText, 1000); ) funksioni flashText() ( var oElem = document.getElementById("kutia e mia"); oElem.style.color = oElem.style.ngjyra == "e kuqe" ? " blu" : "e kuqe"; // oElem.style.color == "e kuqe" ? "blu" : "e kuqe" është një operator tresh. ) funksioni stopTextColor() (clearInterval(nIntervId); )

Pershendetje Bote

Ndalo

Shembulli 3: Simulimi i makinës së shkrimit

Shembulli i mëposhtëm simulon makinën e shkrimit duke pastruar fillimisht dhe më pas duke shtypur ngadalë përmbajtjen në NodeList që përputhet me një grup të caktuar përzgjedhësish.< 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 Typewriter - MDN Shembull i funksionit Makina shkrimi (sSelector, nRate) (funksioni i pastër () (clearInterval(nIntervId); bTyping = false; bStart = true; oCurrent = null; aSheets.length = nIdx = 0; ) funksioni scrollno (PoShet) , bEraseAndStop) ( if (!oSheet.hasOwnProperty("pjesë") || aMap.length

CopyLeft 2012 nga Mozilla Developer Network

[ Luaj | Ndalo | Përfundo]

Vivamus blandit massa ut metus mattis në 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.

Makinë shkrimi 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 tortor sodales non. Sed venenatis luctus magna, ultricies ultricies nunc fringilla eget. Praesent scelerisque urna vitae nibh tristique varius consequat neque luctus. Numri i plotë ornare, erat a porta tempus, velit justo fermentum elit, një fermentum metus nisi eu ipsum. Vivamus eget augue vel dui viverra adipiscing congue ut massa. Praesent vitae eros erat, pulvinar laoreet magna. Maecena vestibulum mollis nunc në posuere. Pellentesque sit amet metus a turpis lobortis tempor eu vel tortor. Cras sodales eleifend interdum.

Duis lobortis sapien quis nisl luctus porttitor. Në 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, në 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.

Argumentet e kthimit të thirrjes

Siç u diskutua më parë, versionet 9 dhe më poshtë të Internet Explorer nuk mbështesin kalimin e argumenteve në funksionin e kthimit të thirrjes as në setTimeout() ose në setInterval(). Kodi i mëposhtëm specifik për IE demonstron një metodë për tejkalimin e këtij kufizimi. Për ta përdorur, thjesht shtoni kodin e mëposhtëm në krye të skriptit tuaj.

/*\ |*| |*| Polyfill specifike për IE që mundëson kalimin e argumenteve arbitrare në |*| funksionet e kthimit të thirrjes së kohëmatësve javascript (sintaksë standarde HTML5)..setInterval |*| https://site/Përdoruesi:fusionchess |*| |*| Sintaksa: |*| var timeoutID = window.setTimeout(funksion, vonesë[, arg1, arg2, ...]); |*| var timeoutID = window.setTimeout(kodi, vonesa); |*| var intervalID = window.setInterval(funksion, vonesë[, arg1, arg2, ...]); |*| var intervalID = dritare.setInterval (kodi, vonesa); |*| \*/ nëse (document.all && !window.setTimeout.isPolyfill) ( var __nativeST__ = window.setTimeout; window.setTimeout = funksion (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etj. */) ( var aArgs = Array .prototype.slice.call(argumente, 2 return __nativeST__(vCallback.apply(null, aArgs); ) : vCallback, nDelay if (document.all && !window.setInterval). ( var __nativeSI__ = window.setInterval; window.setInterval = funksion (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etj. */) ( var aArgs = Array.prototype. slice.call(argumentet, 2); kthej __nativebackSI__(vC shembulli i Funksionit () ( vCallback.apply(null, aArgs); ) : vCallback, nDelay );

Një mundësi tjetër është të përdorni një funksion anonim për të thirrur kthimin tuaj, megjithëse kjo zgjidhje është pak më e shtrenjtë. Shembull:

Var intervalID = setInterval(funksion() ( myFunc ("një", "dy", "tre"); ), 1000);

var intervalID = setInterval(funksioni(arg1) ().bind(e pacaktuar, 10), 1000);

Skedat joaktive Kërkojnë Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)

Duke filluar në Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2), intervalet mbërthehen për të ndezur jo më shpesh se një herë në sekondë në skedat joaktive.

Problemi "ky".

Kur kaloni një metodë te setInterval() ose ndonjë funksioni tjetër, ajo thirret me këtë vlerë të gabuar. Ky problem shpjegohet në detaje në referencën JavaScript.

Shpjegimi

MyArray = ["zero", "një", "dy"]; myArray.myMethod = funksion (sProperty) ( alert(arguments.length > 0 ? this : this); ); myArray.myMethod(); // printon "zero,one,dy" myArray.myMethod(1); // printon "one" setTimeout(myArray.myMethod, 1000); // printon "" pas 1 sekonde setTimeout(myArray.myMethod, 1500, "1"); // printon "të papërcaktuar" pas 1.5 sekondash // duke kaluar objektin "this" me .thirrja nuk do të funksionojë // sepse kjo do të ndryshojë vlerën e kësaj brenda vetë setTimeout // ndërsa ne duam të ndryshojmë vlerën e kësaj brenda myArray .myMethod // në fakt, do të jetë një gabim sepse kodi setTimeout pret që ky të jetë objekti i dritares: setTimeout.call(myArray, myArray.myMethod, 2000, // gabim: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Operacioni i paligjshëm në prototip"; setTimeout.call (myArray, myArray.myMethod, 2500, 2);

Siç mund ta shihni, nuk ka mënyra për të kaluar këtë objekt në funksionin e kthimit të thirrjes në JavaScript të trashëguar.

Një zgjidhje e mundshme

Një mënyrë e mundshme për të zgjidhur problemin "këtë" është zëvendësimi i dy funksioneve globale vendase setTimeout() ose setInterval() me dy jo vendase ato që mundësojnë thirrjen e tyre nëpërmjet metodës Funksioni.prototip.thirrja. Shembulli i mëposhtëm tregon një zëvendësim të mundshëm:

// Aktivizo kalimin e objektit "this" përmes kohëmatësve JavaScript var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval; window.setTimeout = funksion (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etj. */) ( var oThis = kjo, aArgs = Array.prototype.slice.call(argumentet, 2); kthej __nativeST__(vështje e kthimit të thirrjes së funksionit ? () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay ); window.setInterval = funksion (vCallback, nVonesë /*, argumentToPass1, argumentToPass2, etj. */) ( var oThis = kjo, aArgs = Array.prototype.slice.call(argumentet, 2); kthej __nativeSI__(vështja e kthimit të thirrjes së funksionit ? () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay );

Këto dy zëvendësime mundësojnë gjithashtu kalimin standard HTML5 të argumenteve arbitrare në funksionet e kthimit të thirrjes së kohëmatësve në IE. Pra, ato mund të përdoren si jo në përputhje me standardet polifille gjithashtu. Shihni për a në përputhje me standardet polifill

Testi i ri i veçorive:

MyArray = ["zero", "një", "dy"]; myArray.myMethod = funksion (sProperty) ( alert(arguments.length > 0 ? this : this); ); setTimeout (alarm, 1500, "Përshëndetje botë!"); // ruhet përdorimi standard i setTimeout dhe setInterval, por... setTimeout.call(myArray, myArray.myMethod, 2000); // printon "zero, një, dy" pas 2 sekondash setTimeout.call(myArray, myArray.myMethod, 2500, 2); // printon "dy" pas 2,5 sekondash

Për një version më kompleks, por ende modular të tij ( Daemon) shikoni JavaScript Daemons Management. Ky version më kompleks nuk është gjë tjetër veçse një koleksion i madh dhe i shkallëzuar i metodave për Daemon konstruktor. Megjithatë, të Daemon vetë konstruktori nuk është gjë tjetër veçse një klon i MiniDaemon me një mbështetje të shtuar për në fillim dhe fillimi funksionet e deklaruara gjatë instancimit të demon. Kështu që MiniDaemon kornizë mbetet mënyra e rekomanduar për animacione të thjeshta, sepse Daemon pa koleksionin e tij të metodave është në thelb një klon i tij.

minidaemon.js /*\ |*| |*| :: MiniDaemon:: |*| |*| Rishikimi #2 - 26 shtator 2014.setInterval |*| https://site/Përdoruesi:fusionchess |*| https://github.com/madmurphy/minidaemon.js |*| |*| Ky kuadër lëshohet nën licencën GNU Lesser General Public License, versioni 3 ose më i ri. |*| http://www.gnu.org/licenses/lgpl-3.0.html |*| \*/ funksioni MiniDaemon (oOwner, fTask, nRate, nLen) ( if (!(ky && ky shembull i 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 = null; MiniDaemon.prototype.rate = 100; MiniDaemon.prototype.length = Pafundësi;< 1: this.INDEX + 1 >kjo.gjatësia; ); MiniDaemon.prototype.synchronize = funksion () ( if (this.PAUSED) ( return; ) clearInterval(this.SESSION); this.SESSION = setInterval(MiniDaemon.forceCall, this.rate, this); ); MiniDaemon.prototype.pause = funksion () (clearInterval(this.SESSION); this.PAUSED = true; ); MiniDaemon.prototype.start = funksioni (bReverse) ( var bBackw = Boolean(bReverse); if (this.BACKW === bBackw && (this.isAtEnd() || !this.PAUSED)) (kthim; ) this.BACKW = bBackw this.PAUSED = false this.synchronize();

MiniDaemon kalon argumente në funksionin e kthimit të thirrjes. Nëse dëshironi të punoni me shfletues që nuk e mbështesin këtë veçori, përdorni një nga metodat e propozuara më sipër.

Sintaksë

var myDaemon = MiniDaemon i ri( ky Objekti, kthimi i thirrjes[ , norma [, gjatësia]]);

Përshkrimi Shënime të përdorimit

Funksioni setInterval() përdoret zakonisht për të vendosur një vonesë për funksionet që ekzekutohen vazhdimisht, siç janë animacionet. Mund ta anuloni intervalin duke përdorur WindowOrWorkerGlobalScope.clearInterval() .

Nëse dëshironi të thirrni funksionin tuaj një herë pas vonesës së specifikuar, përdorni .

Kufizimet e vonesës

Është e mundur që intervalet të ndërlidhen; domethënë, kthimi i thirrjes për setInterval() mund të thërrasë setInterval() për të filluar një interval tjetër të ekzekutohet, edhe pse i pari vazhdon ende. Për të zbutur ndikimin e mundshëm që mund të ketë në performancës, sapo intervalet të jenë mbivendosur përtej pesë niveleve të thella, shfletuesi do të vendosë automatikisht një vlerë minimale 4 ms për intervalin.

Shfletuesit mund të zbatojnë vlera minimale edhe më të rrepta për intervalin në disa rrethana, megjithëse këto nuk duhet të jenë të zakonshme. Vini re gjithashtu se koha aktuale që kalon ndërmjet thirrjeve drejt kthimit të telefonatës mund të jetë më e gjatë se vonesa e dhënë; shih Arsyet e vonesave më të gjata se sa specifikohet në WindowOrWorkerGlobalScope.setTimeout() për shembuj.

Sigurohuni që kohëzgjatja e ekzekutimit të jetë më e shkurtër se frekuenca e intervalit

Nëse ekziston mundësia që logjika juaj të zgjasë më shumë për t'u ekzekutuar sesa koha e intervalit, rekomandohet që të telefononi në mënyrë rekursive një funksion të emërtuar duke përdorur setTimeout() . Për shembull, nëse përdorni setInterval() për të anketuar një server në distancë çdo 5 sekonda, vonesa e rrjetit, një server që nuk përgjigjet dhe një mori çështjesh të tjera mund të parandalojnë që kërkesa të plotësohet në kohën e caktuar. Si i tillë, ju mund të gjeni veten me kërkesa XHR në radhë që nuk do të kthehen domosdoshmërisht në rregull.

Në programimin në gjuhët e skriptimit, në mënyrë periodike lind nevoja për të krijuar një pauzë - të ndaloni ekzekutimin e programit për një kohë, dhe më pas të vazhdoni të punoni. Për shembull, në skriptet VBS dhe PHP metodat e mëposhtme janë të mundshme:

VBS: wscript.sleep 1500 (ndalo për 1,5 sekonda)

PHP: gjumë (10); (ndaloni për 10 sekonda)

Gjatë pauzave të tilla, sistemi i kohës së funksionimit (PHP ose VBS) nuk bën asgjë. Një zhvillues që përpiqet të përdorë në mënyrë intuitive diçka të ngjashme në Javascript do të befasohet në mënyrë të pakëndshme. Gabim i zakonshëm kur përpiqeni të krijoni një pauzë në Javascript duket kështu:

Funksioni badtest() (për (var i=1; i< 10; i++) { window.setTimeout("document.getElementById("test1").value += " + i, 900) } }

Ju mendoni se kur, gjatë ciklit, vjen radha për të vizatuar numrin tjetër, setTimeout juaj do të ndalojë sinqerisht Javascript të funksionojë, do të prisni 0,9 sekonda, do të shtoni numrin e dëshiruar në fund të fushës së hyrjes dhe më pas do të vazhdoni të punoni. Por në realitet kjo nuk është e vërtetë: setInterval dhe setTimeout në Javascript vetëm vonojnë ekzekutimin e veprimit (ose funksionit) të specifikuar në kllapa. Në shembullin tonë, do të ndodhë si më poshtë:

  • i = 1;
  • vonesa e shtimit të numrit "1" në fushën e hyrjes me 0,9 sekonda;
  • Menjëherë pas vendosjes së këtij problemi, cikli vazhdon: i=2;
  • vonesa e shtimit të numrit "2" në fushën e hyrjes me 0,9 sekonda;
  • Menjëherë do të thotë, për shembull, 1 ms (d.m.th., në mënyrë disproporcionale të vogël në krahasim me 900 ms): cikli do të bëjë punën e tij pothuajse menjëherë, duke krijuar disa detyra të shtyra nga e njëjta pikë në kohë. Kjo do të thotë që të gjitha detyrat në pritje të "vizatimit" do të përfundojnë pothuajse në të njëjtën kohë, pa pauza midis shtimit të numrave të rinj. Cikli fillon; gjithçka ngrin për 0,9 s; dhe shirr - të gjithë numrat janë qëlluar me radhë njëri pas tjetrit.

    Si të aplikoni saktë setTimeout në një rast të tillë? Është e komplikuar. Ju do të duhet të telefononi funksionin në mënyrë rekursive(nga brenda funksionit i njëjti funksion), dhe në mënyrë që ky proces të mos jetë i pafund, vendosni një kusht ndalimi (për shembull, madhësia e numrit që do të printohet):

    Funksioni welltest() (nëse (i< 9) { document.getElementById("test2").value += ++i window.setTimeout("welltest()", 400) } }

    Dhe ndryshorja i do të duhet të inicializohet jashtë funksionit - për shembull, si kjo:

    Tani gjithçka funksionon ashtu siç duhet (reduktuam kohën e vonesës nga 0,9 s në 0,4 s). Por për detyra të tilla, është më logjike të përdoret setInterval në vend të setTimeout (megjithëse kjo do të kërkojë dy funksione):

    Funksioni besttest() ( window.i = 0 window.timer1 = window.setInterval("draw()", 400) ) funksion draw() ( document.getElementById("test3").vlera += ++i if (i >= 9) clearInterval(window.timer1) )

    E veçanta e metodës Javascirpt setInterval është se ajo nuk kalon "vetëvetiu" ajo duhet të ndalet me një metodë të veçantë clearInterval. Dhe për të bërë të qartë se çfarë saktësisht duhet të ndalet, detyrës për veprimin e shtyrë i caktohet një identifikues i veçantë - një kohëmatës: window.timer1 = window.setInterval(...) .

    Identifikuesit mund t'u caktohen gjithashtu detyrave të krijuara nga metoda setTimeout. Të gjitha ID-të e kohëmatësit duhet të jenë të dallueshme nga njëra-tjetra (unike brenda dritares aktuale të shfletuesit). Më pas mund të krijoni disa detyra të ndryshme në dritare që përdorin veprime të shtyra, dhe këto detyra do të ekzekutohen paralelisht (një lloj në të njëjtën kohë, nëse kompjuteri ka burime të mjaftueshme), gjë që në thelb është e pamundur në PHP ose VBS.

    Këtu është një shembull i një faqeje me disa kohëmatës Javascript që funksionojnë njëkohësisht: setinterval.htm (funksionet Javascript në skedarin setinterval.js). Të gjithë kohëmatësit e faqeve (përveç menysë) mund të ndalen duke përdorur tastin Esc. Të gjithë kohëmatësit e shembujve bazohen në një numërim "natyror" (dhe jo abstrakt i++) - kohë ose distancë. Të gjitha "orët" janë të desinkronizuara posaçërisht (për qartësi). Kohëmatësit e varur nga distanca përdoren në menynë "tregues" dhe në menynë rënëse ("tërheqje").

    Menyja rënëse

    Menyja jonë rrëshqitëse është në të vërtetë rrëshqitëse (nga poshtë "titullit"): boshllëqet lihen posaçërisht midis elementeve në mënyrë që të mund të shihni se si rrëshqet jashtë. Papritur, doli që ne nuk mund ta bënim daljen po aq të qetë për listat me gjatësi të ndryshme - ndoshta për shkak të performancës së ulët të kompjuterit (AMD Athlon 999 MHz).

    Është mjaft e qartë se për bukurinë dhe harmoninë është e nevojshme që listat e artikujve të ndryshëm të menusë të shfaqen në të njëjtën kohë. Kjo do të thotë, listat më të gjata duhet të bien me më shumë shpejtësi të lartë, ato më të shkurtra - me një shpejtësi më të ulët. Duket se kjo mund të zbatohet si kjo:

  • Ne vendosëm kohën totale të "nisjes", për shembull, në 200 ms.
  • Nëse lista zbritëse ka një lartësi prej 20 px, është e qartë se ne mund ta lëvizim atë një piksel poshtë për një interval 10 ms - dhe më pas në 200 ms e gjithë lista do të dalë.
  • Nëse menyja e lëshimit është 40 pikselë e lartë, për t'u përshtatur në të njëjtën kohë duhet ta zhvendosim një piksel poshtë çdo 5 ms.
  • Sipas kësaj logjike, nëse lista e zbritjes është 200 px e lartë, ne duhet ta zhvendosim atë një piksel poshtë çdo 1 ms. Por një shpejtësi e tillë nuk funksionon në kompjuterin tonë - shfletuesi thjesht nuk ka kohë të tërheqë pozicionin e ri të listës në një milisekondë. po. Javascript arrin të numërojë (çfarë ka për të numëruar?), por shfletuesi (Firefox) nuk ka kohë për të shfaqur. Situata tipike për ueb.

    Prandaj, është e mundur që pak a shumë të barazohet koha e nisjes së menusë vetëm me ndihmën e patericave, dhe është ende e paqartë se si do të funksionojë kjo për më shumë kompjuter i shpejtë. Por ne duhet të llogarisim në atë më të ngadaltë, apo jo? Algoritmi (pa marrë parasysh shpejtësinë e kompjuterit) rezulton diçka e tillë:

  • Caktoni kohën totale për të kontrolluar listën: koha = 224 (ms).
  • Ne vendosim kohën minimale për një interval në cikël: vonesë = 3 (ms).
  • Vendosni hapin minimal për lëvizjen e listës: offset = 1 (px).
  • Të gjitha këto i ndryshojmë në varësi të lartësisë së listës: 1) rrisim kohën e vonesës (intervalit) në përpjesëtim të zhdrejtë me lartësinë dhe drejtpërdrejt proporcionale me kohën totale të kohës (në lartësinë 224 koeficienti është 1); 2) nëse lartësia është më e madhe se 40 px, rritni hapin minimal në proporcion me lartësinë. Konstantja "40" u mor eksperimentalisht për kompjuterin më të ngadaltë. Testet në një kompjuter Pentium 4 CPU 2.53 GHz zbuluan saktësisht të njëjtin numër - 40. Përndryshe, kohëmatësit dalin jashtë funksionit, listat dalin jashtë hapit.
  • Tani pak a shumë po dalin listat. Për një kohë pak a shumë të ngjashme. Në faqen setinterval.htm.

    Dhe këtu vjen Bruce:

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

    Vetë funksioni, i cili i shtyn listat e mbivendosura jashtë menysë, është, siç mund ta shohim, shumë i thjeshtë. Gjithçka që mbetet është ta ekzekutoni me diçka si kjo linjë:

    Ts.timer1 = setInterval(funksion())(slide_do(ts, maxtop, offset)), vonesë)

    Epo, para se të filloni, thjesht llogaritni të gjitha këto maxtop dhe offset, dhe gjithashtu vendosni listën në pozicionin e mintopit. Kjo është ajo që bën funksioni "preliminar" slide() i 40 rreshtave. Dhe të gjithë së bashku - në skedarin setinterval.js. Po, dhe kjo mut nuk do të funksionojë fare pa skedarin e stileve të përfshira

    Është jashtëzakonisht e rëndësishme të kuptohet se si funksionojnë kohëmatësit JavaScript. Shpesh sjellja e tyre nuk përputhet me kuptimin tonë intuitiv të multithreading, dhe kjo për faktin se në realitet ato ekzekutohen në një fije të vetme. Le të shohim katër funksione me të cilat mund të menaxhojmë kohëmatësit:

    • var id = setTimeout(fn, vonesë); - Krijon një kohëmatës të thjeshtë që do të thërrasë një funksion të caktuar pas një vonese të caktuar. Funksioni kthen një ID unike me të cilën kohëmatësi mund të ndërpritet.
    • var id = setInterval(fn, vonesë); - Ngjashëm me setTimeout, por thërret vazhdimisht funksionin në një interval të caktuar (derisa të ndalet).
    • clearInterval(id);, clearTimeout(id); - Pranon një ID të kohëmatësit (të kthyer nga një prej funksioneve të përshkruara më sipër) dhe ndalon ekzekutimin e kthimit të thirrjes"a.
    Ideja kryesore për t'u marrë parasysh është se saktësia e periudhës së vonesës së kohëmatësit nuk është e garantuar. Për të filluar, shfletuesi ekzekuton të gjitha ngjarjet asinkrone të JavaScript në një thread (të tilla si klikimet e miut ose kohëmatësit) dhe vetëm në kohën kur është radha e asaj ngjarjeje. Kjo tregohet më së miri nga diagrami i mëposhtëm:

    Ka mjaft informacion për të marrë në këtë figurë, por kuptimi i tij do t'ju japë një kuptim më të thellë se si funksionon asinkronia JavaScript. Ky grafik paraqet kohën vertikalisht në milisekonda, blloqet blu tregojnë blloqet e kodit JavaScript që janë ekzekutuar. Për shembull, blloku i parë ekzekutohet mesatarisht në 18 ms, një klikim i mausit bllokon ekzekutimin për rreth 11 ms, etj.

    JavaScript mund të ekzekutojë vetëm një copë kodi (për shkak të natyrës së ekzekutimit me një fije), secila prej të cilave bllokon ekzekutimin e ngjarjeve të tjera asinkrone. Kjo do të thotë që kur ndodh një ngjarje asinkrone (siç është një klikim i mausit, një thirrje me kohëmatës ose përfundimi i një kërkese XMLHttp), ai shtohet në një radhë dhe ekzekutohet më vonë (zbatimi ndryshon sipas shfletuesit, natyrisht, por le të biem dakord me quaj atë një "radhë").

    Për të filluar, le të imagjinojmë që dy kohëmatës fillojnë brenda një blloku JavaScript: setTimeout me një vonesë prej 10 ms dhe setInterval me të njëjtën vonesë. Në varësi të kohës kur fillon kohëmatësi, ai do të ndizet në momentin kur nuk kemi përfunduar ende bllokun e parë të kodit. Megjithatë, vini re se nuk ndizet menjëherë (kjo nuk është e mundur për shkak të filetimit të vetëm). Në vend të kësaj, funksioni i shtyrë vihet në radhë dhe ekzekutohet në momentin tjetër të disponueshëm.

    Gjithashtu, gjatë ekzekutimit të bllokut të parë JavaScript, ndodh një klikim i mausit. Trajtuesi për këtë ngjarje asinkrone (dhe është asinkron sepse ne nuk mund ta parashikojmë) nuk mund të ekzekutohet drejtpërdrejt në këtë moment, kështu që ai gjithashtu përfundon në një radhë, si kohëmatësi.

    Pasi të jetë ekzekutuar blloku i parë i kodit JavaScript, shfletuesi shtron pyetjen, "Çfarë pret të ekzekutohet?" NË në këtë rast Trajtësi i klikimeve të miut dhe kohëmatësi janë në një gjendje pezull. Shfletuesi zgjedh një prej tyre (trajtuesin e klikimeve) dhe e ekzekuton atë. Kohëmatësi do të presë për pjesën tjetër të disponueshme të kohës në radhën e ekzekutimit.

    Vini re se ndërsa mbajtësi i klikimeve të miut është duke ekzekutuar, ndizet kthimi i thirrjes së parë në interval. Ashtu si kthimi i thirrjes me kohëmatës, do të jetë në radhë. Megjithatë, kini parasysh se kur intervali ndizet përsëri (ndërsa kohëmatësi-thirrje është në punë), ai do të hiqet nga radha. Nëse të gjitha kthimet e intervalit do të vendoseshin në radhë gjatë ekzekutimit të një pjese të madhe të kodit, kjo do të rezultonte në një grup funksionesh që presin për t'u thirrur, pa periudha vonese mes tyre duke përfunduar ekzekutimin, në vend të kësaj, shfletuesit priren të presin derisa të mos ketë më funksione lënë në radhë përpara se të shtoni një tjetër në radhë.

    Kështu, ne mund të vëzhgojmë rastin kur shkrepja e tretë e intervalit të thirrjes përkon me momentin kur ai tashmë është ekzekutuar. Kjo ilustron një pikë të rëndësishme: intervaleve nuk u intereson se çfarë po ekzekutohet aktualisht, ato do të shtohen në radhë pa marrë parasysh periudhën e vonesës midis ekzekutimeve.

    Më në fund, pasi të përfundojë kthimi i intervalit të dytë, do të shohim se nuk ka mbetur asgjë për të ekzekutuar motorin JavaScript. Kjo do të thotë që shfletuesi përsëri pret që të ndodhin ngjarje të reja asinkrone. Kjo do të ndodhë në shenjën 50 ms, ku kthimi i intervalit do të funksionojë përsëri. Në këtë pikë nuk do të ketë asgjë për ta bllokuar, kështu që do të funksionojë menjëherë.

    Le të shohim një shembull që ilustron bukur ndryshimin midis setTimeout dhe setInterval.
    setTimeout(funksion())( /* Disa bllok të gjatë kodi... */ setTimeout(arguments.callee, 10); ), 10);
    setInterval(funksion())( /* Disa bllok të gjatë kodi... */ ), 10);

    Këto dy opsione janë ekuivalente në shikim të parë, por në realitet nuk janë. Kodi që përdor setTimeout do të ketë gjithmonë një vonesë prej të paktën 10 ms pas thirrjes së mëparshme (mund të jetë më shumë, por asnjëherë më pak), ndërsa kodi që përdor setInterval do të priret të thirret çdo 10 ms, pavarësisht se kur ka ndodhur thirrja e mëparshme.
    Le të përmbledhim gjithçka që u tha më sipër:
    - Funksionet setTimeout dhe setInterval ekzekutohen krejtësisht ndryshe në kodin asinkron,
    - Nëse kohëmatësi nuk mund të ekzekutohet në për momentin, do të vonohet deri në pikën tjetër të ekzekutimit (e cila do të jetë më e gjatë se vonesa e dëshiruar),
    - Intervalet (setInterval) mund të ekzekutohen njëra pas tjetrës pa vonesë nëse ekzekutimi i tyre zgjat më shumë se vonesa e specifikuar.

    E gjithë kjo është jashtëzakonisht informacione të rëndësishme për zhvillim. Njohja se si funksionon motori JavaScript, veçanërisht me shumë ngjarje asinkrone (gjë që ndodh shpesh), hedh një themel të madh për ndërtimin e aplikacioneve të avancuara.

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

    Pothuajse të gjitha implementimet e JavaScript kanë një programues të brendshëm të kohëmatësit që ju lejon të planifikoni një funksion që do të thirret pas një periudhe të caktuar kohe.

    Në veçanti, kjo veçori mbështetet në shfletues dhe në serverin Node.JS.

    setTimeout

    Sintaksa:

    var timerId = setTimeout (funksioni/kodi, vonesa[, arg1, arg2...])

    Parametrat:

    • funksion/kod
      • Një funksion ose linjë kodi që do të ekzekutohet.
      • Vargu ruhet për qëllime të përputhshmërisë dhe nuk rekomandohet.
    • func
      • Vonesa në milisekonda, 1000 milisekonda është e barabartë me 1 sekondë.
    • arg1, arg2…
      • Argumentet për të kaluar në funksion. Nuk mbështetet në IE9-.
      • Funksioni do të ekzekutohet pas kohës së specifikuar në parametrin e vonesës.

    Për shembull, kodi i mëposhtëm do të aktivizojë alarmin ("Përshëndetje") pas një sekonde:

    funksioni func () ( alarm ("Përshëndetje"); ) setTimeout(func, 1000);

    Nëse argumenti i parë është një varg, atëherë interpretuesi krijon një funksion anonim nga ai varg.

    Kjo do të thotë, kjo hyrje funksionon saktësisht njësoj:

    SetTimeout("alarm("Përshëndetje")", 1000);

    Në vend të kësaj, përdorni funksione anonime:

    SetTimeout(funksioni () ( alarm ("Përshëndetje" ) ), 1000 );

    Parametrat për funksionin dhe kontekstin

    Në të gjitha shfletues modern Duke pasur parasysh IE10, setTimeout ju lejon të specifikoni parametrat e funksionit.

    Shembulli më poshtë do të nxjerrë "Përshëndetje, unë jam Vasya" kudo përveç IE9-:

    funksioni sayHi (kush) ( alarm ("Përshëndetje, unë jam " + kush); ) setTimeout(sayHi, 1000, "Vasya");

    ...Megjithatë, në shumicën e rasteve kemi nevojë për mbështetje nga IE-ja e vjetër dhe nuk ju lejon të specifikoni argumente. Prandaj, për t'i transferuar ato, ata e mbyllin thirrjen në një funksion anonim:

    funksioni sayHi (kush) ( alert ("Përshëndetje, unë jam " + kush); ) setTimeout(funksioni () ( sayHi ("Vasya") ), 1000 );

    Thirrja e setTimeout nuk e kalon këtë kontekst.

    Në veçanti, thirrja e një metode objekti përmes setTimeout do të funksionojë në kontekstin global. Kjo mund të çojë në rezultate të pasakta.

    Për shembull, le të thërrasim user.sayHi() pas një sekonde:

    funksioni Përdoruesi (id) Funksioni () ( alert(this .id); ); ) var përdorues = përdorues i ri (12345); setTimeout(user.sayHi, 1000); // pritet 12345, por do të dalë "i papërcaktuar"

    Meqenëse setTimeout do të ekzekutojë funksionin user.sayHi në kontekstin global, ai nuk do të ketë akses në objekt nëpërmjet kësaj .

    Me fjalë të tjera, këto dy thirrje për setTimeout bëjnë të njëjtën gjë:

    // (1) një rresht setTimeout(user.sayHi, 1000); // (2) e njëjta gjë në dy rreshta var func = user.sayHi; setTimeout (funksion, 1000 );

    Për fat të mirë, ky problem gjithashtu zgjidhet lehtësisht duke krijuar një funksion të ndërmjetëm:

    funksioni Përdoruesi (id) (ky .id = id; ky .sayHi = funksioni () ( alarm(this .id); ) var përdorues = Përdoruesi i ri (12345); setTimeout(funksioni () ( user.sayHi(); ), 1000 );

    Një funksion mbështjellës përdoret për të kaluar argumentet në një shfletues të kryqëzuar dhe për të ruajtur kontekstin e ekzekutimit.

    Anulimi i ekzekutimit

    Funksioni setTimeout kthen një timerId që mund të përdoret për të anuluar veprimin.

    Sintaksa:

    ClearTimeout (TimerId)

    Në shembullin e mëposhtëm, vendosëm një afat kohor dhe më pas fshijmë (ndryshuam mendjen). Si rezultat, asgjë nuk ndodh.

    var timerId = setTimeout(funksioni () ( alarm (1) ), 1000 ); clearTimeout (timerId); setInterval

    Metoda setInterval ka një sintaksë të ngjashme me setTimeout.

    var timerId = setInterval (funksioni/kodi, vonesa[, arg1, arg2...])

    Kuptimi i argumenteve është i njëjtë. Por, ndryshe nga setTimeout, ai nuk e ekzekuton funksionin një herë, por e përsërit rregullisht në një interval kohor të caktuar. Mund ta ndaloni ekzekutimin duke telefonuar:

    ClearInterval (Id timer)

    Shembulli i mëposhtëm, kur ekzekutohet, do të shfaqë një mesazh çdo dy sekonda derisa të klikoni butonin Stop:

    var i = 1;

    var timer = setInterval(funksioni () ( alarm(i++) ), 2000 );

    Në radhë dhe mbivendosja e thirrjeve në setInterval

    Thirrja setInterval (funksioni, vonesa) bën që funksioni të ekzekutohet në intervalin kohor të caktuar. Por këtu ka një hollësi.

    Në fakt, pauza ndërmjet thirrjeve është më e vogël se intervali i specifikuar.

    Kjo do të thotë, shfletuesi fillon nisjen e funksionit mjeshtërisht çdo 100 ms, pa marrë parasysh kohën e ekzekutimit të vetë funksionit.

    Ndodh që ekzekutimi i një funksioni të zgjasë më shumë se vonesa. Për shembull, funksioni është kompleks, por vonesa është e vogël. Ose funksioni përmban deklarata alarmi / konfirmoni / nxitëse që bllokojnë fillin e ekzekutimit. Këtu gjërat fillojnë të bëhen interesante.

    Nëse një funksion nuk mund të hapet sepse shfletuesi është i zënë, ai do të vendoset në radhë dhe do të ekzekutohet sapo shfletuesi të jetë i lirë.

    Imazhi më poshtë ilustron se çfarë ndodh me një funksion që kërkon shumë kohë për t'u ekzekutuar.

    Thirrja e funksionit e nisur nga setInterval shtohet në radhë dhe ndodh menjëherë kur është e mundur:

    Nisja e dytë e funksionit ndodh menjëherë pas përfundimit të të parit:

    Ekzekutimi nuk është në radhë më shumë se një herë.

    Nëse një funksion kërkon më shumë kohë për t'u ekzekutuar se disa ekzekutime të planifikuara, ai përsëri do të qëndrojë në radhë një herë. Pra, nuk ka "akumulim" të nisjeve.

    Në imazhin më poshtë, setInterval përpiqet të ekzekutojë funksionin në 200 ms dhe vendos thirrjen në radhë. Në 300ms dhe 400ms kohëmatësi zgjohet përsëri, por asgjë nuk ndodh.

    Thirrja e setInterval (funksioni, vonesa) nuk garanton vonesë aktuale midis ekzekutimeve.

    Ka raste kur vonesa aktuale është më e madhe ose më e vogël se ajo e specifikuar. Në përgjithësi, nuk është fakt se do të ketë të paktën një vonesë.

    Përsëritja e vendosjes së mbivendosurTimeout

    Në rastet kur nevojitet jo vetëm përsëritje e rregullt, por kërkohet një vonesë midis ekzekutimeve, setTimeout përdoret për të ri-konfiguruar çdo herë që funksioni ekzekutohet.

    Më poshtë është një shembull që lëshon një alarm me intervale 2 sekondash mes tyre.

    var i = 1;

    var timer = setTimeout (funksioni ekzekutohet () ( alarm (i++); timer = setTimeout (run, 2000); ), 2000);

    Afati kohor i ekzekutimit do të ketë vonesa fikse ndërmjet ekzekutimeve. Ilustrim për vonesën 100ms:

    Vonesa minimale e kohëmatësit

    Kohëmatësi i shfletuesit ka vonesën më të ulët të mundshme. Ndryshon nga afërsisht zero në 4ms në shfletuesit modernë. Tek më të vjetrat mund të jetë më i gjatë dhe të arrijë 15 ms.

    Sipas standardit, vonesa minimale është 4 ms. Pra, nuk ka asnjë ndryshim midis setTimeout (..,1) dhe setTimeout (..,4).

  • Sjellja me vonesë zero e setTimeout dhe setInterval është specifike për shfletuesin.
  • Në Internet Explorer, zero vonesë setInterval (.., 0) nuk do të funksionojë. Kjo vlen veçanërisht për setInterval, d.m.th. setTimeout (.., 0) funksionon mirë.
  • Frekuenca aktuale e nxitjes

    Aktivizimi mund të jetë shumë më pak i shpeshtë Në disa raste, vonesa mund të mos jetë 4 ms, por 30 ms ose edhe 1000 ms.

    Shumica e shfletuesve (kryesisht ata të desktopit) vazhdojnë të ekzekutojnë setTimeout / setInterval edhe nëse skeda është joaktive. Në të njëjtën kohë, një numër prej tyre (Chrome, FF, IE10) reduktojnë frekuencën minimale të kohëmatësit në 1 herë në sekondë. Rezulton se kohëmatësi do të funksionojë në skedën "sfondi", por rrallë.

    Kur funksionon me energji baterie, në një laptop, shfletuesit gjithashtu mund të zvogëlojnë frekuencën për të ekzekutuar kodin më rrallë dhe për të kursyer energjinë e baterisë. IE është veçanërisht i famshëm për këtë. Zvogëlimi mund të arrijë disa herë, në varësi të cilësimeve. Nëse ngarkesa e CPU-së është shumë e lartë, JavaScript mund të mos jetë në gjendje të përpunojë kohëmatësit në kohën e duhur. Kjo do të kapërcejë disa ekzekutime të setInterval.

    Përfundim: ia vlen të përqendroheni në një frekuencë prej 4 ms, por nuk duhet të mbështeteni në të.

    Dalja e intervaleve në tastierë Kodi që numëron intervalet kohore ndërmjet thirrjeve duket diçka si kjo:

    var timeMark = Data e re; setTimeout(funksioni go () ( var diff = ri Data - TimeMark; // printoni vonesën e radhës në tastierë në vend të konsolës së faqes .log(diff); // mbani mend kohën në fund, // për të matur vonesë ndërmjet thirrjeve timeMark = data e re SetTimeout(shko, 100 ), 100 ; Truku është setTimeout (funksion, 0)

    Ky mashtrim është i denjë për të hyrë në analet e hakimeve të JavaScript.

    Funksioni është i mbështjellë në setTimeout(func, 0) nëse dëshironi ta ekzekutoni pas përfundimit të skriptit aktual.

    Puna është se setTimeout nuk e ekzekuton kurrë funksionin menjëherë. Ai vetëm planifikon zbatimin e tij. Por interpretuesi JavaScript do të fillojë të kryejë funksionet e planifikuara vetëm pasi të ekzekutohet skripti aktual.

    Sipas standardit, setTimeout nuk mund të ekzekutojë një funksion me një vonesë prej 0 gjithsesi. Por gjëja kryesore këtu është se ekzekutimi në çdo rast do të bëhet pas ekzekutimit të kodit aktual.

    Për shembull:

    rezultat var; funksioni showResult () ( alarm(rezultat); ) setTimeout(shfaqRezultatin, 0 ); rezultat = 2 * 2 ; // do të nxjerrë 4 Total

    Metodat setInterval(func, vonesë) dhe setTimeout(func, vonesë) ju lejojnë të ekzekutoni funksionin rregullisht/një herë në çdo milisekonda vonesë.

    Të dyja metodat kthejnë ID-në e kohëmatësit. Përdoret për të ndaluar ekzekutimin duke thirrur clearInterval/clearTimeout.

    | | setInterval | setTimeout | || ----------- | ---------- | | Koha | Thirrja është rreptësisht në një kohëmatës. Nëse përkthyesi është i zënë, një telefonatë është në radhë. Koha e ekzekutimit të funksionit nuk merret parasysh, kështu që intervali kohor nga fundi i një ekzekutimi deri në fillimin e një tjetri mund të ndryshojë. | Një thirrje rekursive për setTimeout përdoret në vend të setInterval ku nevojitet një pauzë fikse midis ekzekutimeve. | | Vonesa | Vonesa minimale: 4 ms. | Vonesa minimale: 4 ms. | | Karakteristikat e shfletuesit | Vonesa 0 nuk funksionon në IE | Në Opera, vonesa zero është e barabartë me 4ms dhe vonesat e tjera trajtohen me saktësi, duke përfshirë 1ms, 2ms dhe 3ms jo standarde. |

    © 2024 ermake.ru -- Rreth riparimit të PC - Portali informacioni