WindowOrWorkerGlobalScope mixin 的 setInterval() 方法反復(fù)調(diào)用一個(gè)函數(shù)或執(zhí)行一個(gè)代碼片段,每次調(diào)用之間有一個(gè)固定的時(shí)間延遲。它返回一個(gè)唯一標(biāo)識(shí)時(shí)間間隔的 interval ID,以便稍后可以通過(guò)調(diào)用 clearInterval() 將其刪除。這種方法在 Window 與 Worker 接口提供。
var intervalID = scope.setInterval(func,delay [,param1,param2,...]);
var intervalID = scope.setInterval(code,delay);
func
delay
毫秒執(zhí)行一次 function 。該函數(shù)不傳遞任何參數(shù),并且沒(méi)有返回值。code
delay
毫秒編譯和執(zhí)行的函數(shù)。不建議出于使用eval()
安全風(fēng)險(xiǎn)的相同原因而使用此語(yǔ)法。delay
param1, ..., paramN
可選的注意:在 Internet Explorer 9 及更早版本中,以第一種語(yǔ)法向 setInterval() 傳遞附加參數(shù)不起作用。如果您想在該瀏覽器上啟用此功能,則必須使用填充。
返回值 intervalID 是一個(gè)非零的數(shù)值,用于標(biāo)識(shí)由調(diào)用 setInterval() 創(chuàng)建的計(jì)時(shí)器;這個(gè)值可以傳遞給 WindowOrWorkerGlobalScope.clearInterval() 以取消超時(shí)。
了解 setInterval() 和 setTimeout() 共享相同的 ID 池可能會(huì)有所幫助,并且技術(shù)上可以互換使用 clearInterval() 和 clearTimeout() 可能會(huì)有幫助。但是,為了清晰起見(jiàn),您應(yīng)該盡量始終與它們匹配以避免在維護(hù)代碼時(shí)出現(xiàn)混淆。
注意:delay 參數(shù)被轉(zhuǎn)換為有
符號(hào)的32位整數(shù)。這有效地限制delay 為2147483647毫秒,因?yàn)樗贗DL中被指定為有符號(hào)整數(shù)。
以下示例演示了setInterval()基本語(yǔ)法:
var intervalID = window.setInterval(myCallback, 500);
function myCallback() {
// Your code here
}
以下示例 flashtext() 每秒調(diào)用一次該功能,直到按下停止按鈕:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>setInterval/clearInterval example</title>
<script>
var nIntervId;
function changeColor() {
nIntervId = setInterval(flashText, 1000);
}
function flashText() {
var oElem = document.getElementById('my_box');
oElem.style.color = oElem.style.color == 'red' ? 'blue' : 'red';
// 'red' ? 'blue' : 'red' is a ternary operator.
}
function stopTextColor() {
clearInterval(nIntervId);
}
</script>
</head>
<body onload="changeColor();">
<div id="my_box">
<p>Hello World</p>
</div>
<button onclick="stopTextColor();">Stop</button>
</body>
</html>
以下示例首先清除打字機(jī),然后將內(nèi)容緩慢地鍵入與指定的一組選擇器匹配的 NodeList 中,從而模擬打字機(jī):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>JavaScript Typewriter - MDN Example</title>
<script>
function Typewriter (sSelector, nRate) {
function clean () {
clearInterval(nIntervId);
bTyping = false;
bStart = true;
oCurrent = null;
aSheets.length = nIdx = 0;
}
function scroll (oSheet, nPos, bEraseAndStop) {
if (!oSheet.hasOwnProperty('parts') || aMap.length < nPos) { return true; }
var oRel, bExit = false;
if (aMap.length === nPos) { aMap.push(0); }
while (aMap[nPos] < oSheet.parts.length) {
oRel = oSheet.parts[aMap[nPos]];
scroll(oRel, nPos + 1, bEraseAndStop) ? aMap[nPos]++ : 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[nIdx], 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[nChild]);
this.parts[nChild] = new Sheet(this.parts[nChild]);
}
}
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[nItem]));
/* Uncomment the following line if you have previously hidden your elements via CSS: */
// aItems[nItem].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[nIdx++], 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();
};
</script>
<style type="text/css">
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; */
}
</style>
</head>
<body>
<p id="copyleft" style="font-style: italic; font-size: 12px; text-align: center;">CopyLeft 2012 by <a rel="external nofollow" target="_blank" target="_blank">Mozilla Developer Network</a></p>
<p id="controls" style="text-align: center;">[ <span class="intLink" onclick="oTWExample1.play();">Play</span> | <span class="intLink" onclick="oTWExample1.pause();">Pause</span> | <span class="intLink" onclick="oTWExample1.terminate();">Terminate</span> ]</p>
<div id="info">
Vivamus blandit massa ut metus mattis in fringilla lectus imperdiet. Proin ac ante a felis ornare vehicula. Fusce pellentesque lacus vitae eros convallis ut mollis magna pellentesque. Pellentesque placerat enim at lacus ultricies vitae facilisis nisi fringilla. In tincidunt tincidunt tincidunt.
</div>
<h1>JavaScript Typewriter</h1>
<div id="article">
<p>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.</p>
<form>
<p>Phasellus ac nisl lorem: <input type="text" /><br />
<textarea style="width: 400px; height: 200px;">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. Integer ornare, erat a porta tempus, velit justo fermentum elit, a fermentum metus nisi eu ipsum. Vivamus eget augue vel dui viverra adipiscing congue ut massa. Praesent vitae eros erat, pulvinar laoreet magna. Maecenas vestibulum mollis nunc in posuere. Pellentesque sit amet metus a turpis lobortis tempor eu vel tortor. Cras sodales eleifend interdum.</textarea></p>
<p><input type="submit" value="Send" />
</form>
<p>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.</p>
<p>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.</p>
</div>
</body>
</html>
查看此演示中的操作。另見(jiàn):clearInterval()。
如前所述,Internet Explorer 9 和下面不支持將參數(shù)傳遞給 setTimeout () 或 setInterval () 中的回調(diào)函數(shù)。以下的 IE 特定的代碼演示了克服此限制的方法。要使用,只需將以下代碼添加到腳本的頂部。
/*\
|*|
|*| IE-specific polyfill that enables the passage of arbitrary arguments to the
|*| callback functions of javascript timers (HTML5 standard syntax).
|*|
|*| https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval
|*| https://developer.mozilla.org/User:fusionchess
|*|
|*| Syntax:
|*| var timeoutID = window.setTimeout(func, delay[, param1, param2, ...]);
|*| var timeoutID = window.setTimeout(code, delay);
|*| var intervalID = window.setInterval(func, delay[, param1, param2, ...]);
|*| var intervalID = window.setInterval(code, delay);
|*|
\*/
if (document.all && !window.setTimeout.isPolyfill) {
var __nativeST__ = window.setTimeout;
window.setTimeout = function (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 = function (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;
}
另一種可能性是使用匿名函數(shù)來(lái)調(diào)用你的回調(diào)函數(shù),雖然這個(gè)解決方案有點(diǎn)消耗。例:
var intervalID = setInterval(function() { myFunc('one', 'two', 'three'); }, 1000);
另一種可能性是使用函數(shù)的綁定,例如:
var intervalID = setInterval(function(arg1) {}.bind(undefined, 10), 1000);
提示:需要 Gecko 5.0(Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)
從 Gecko 5.0(Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)開(kāi)始,間隔在非活動(dòng)標(biāo)簽中被限制為每秒不超過(guò)一次。
當(dāng)你傳遞一個(gè)方法到 setInterval() 或者其他函數(shù)時(shí),它會(huì)被錯(cuò)誤的 this 值調(diào)用。
由 setInterval() 執(zhí)行的代碼在單獨(dú)的執(zhí)行上下文中運(yùn)行,而不是調(diào)用它的函數(shù)。因此,被調(diào)用函數(shù)的 this 關(guān)鍵字被設(shè)置為 window(或 global)對(duì)象,它與調(diào)用 setTimeout 的函數(shù)的 this 值不同??聪旅娴睦樱ㄋ?setTimeout() 代替 setInterval(),這兩個(gè)計(jì)時(shí)器的問(wèn)題實(shí)際上是相同的):
myArray = ['zero', 'one', 'two'];
myArray.myMethod = function (sProperty) {
alert(arguments.length > 0 ? this[sProperty] : this);
};
myArray.myMethod(); // prints "zero,one,two"
myArray.myMethod(1); // prints "one"
setTimeout(myArray.myMethod, 1000); // prints "[object Window]" after 1 second
setTimeout(myArray.myMethod, 1500, "1"); // prints "undefined" after 1,5 seconds
// passing the 'this' object with .call won't work
// because this will change the value of this inside setTimeout itself
// while we want to change the value of this inside myArray.myMethod
// in fact, it will be an error because setTimeout code expects this to be the window object:
setTimeout.call(myArray, myArray.myMethod, 2000); // error: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Illegal operation on WrappedNative prototype object"
setTimeout.call(myArray, myArray.myMethod, 2500, 2); // same error
正如你所看到的,沒(méi)有辦法將 this 對(duì)象傳遞給傳統(tǒng) JavaScript 中的回調(diào)函數(shù)。
解決這個(gè) this 問(wèn)題的一種可能的方法是,使用兩個(gè)非本地的函數(shù)替換兩個(gè)本地的 setTimeout() 或 setInterval() 全局函數(shù),這兩個(gè)函數(shù)通過(guò)該 Function.prototype.call 方法啟用它們的調(diào)用。以下示例顯示了可能的更換:
// Enable the passage of the 'this' object through the JavaScript timers
var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval;
window.setTimeout = function (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);
};
這兩個(gè)替代方案還使得 HTML5 標(biāo)準(zhǔn)可以將任意參數(shù)傳遞給IE中定時(shí)器的回調(diào)函數(shù)。
因此它們也可以用作非標(biāo)準(zhǔn)兼容的 polyfill。
新功能測(cè)試:
myArray = ['zero', 'one', 'two'];
myArray.myMethod = function (sProperty) {
alert(arguments.length > 0 ? this[sProperty] : this);
};
setTimeout(alert, 1500, 'Hello world!'); // the standard use of setTimeout and setInterval is preserved, but...
setTimeout.call(myArray, myArray.myMethod, 2000); // prints "zero,one,two" after 2 seconds
setTimeout.call(myArray, myArray.myMethod, 2500, 2); // prints "two" after 2,5 seconds
另一個(gè)更復(fù)雜的解決方案是以下框架。
JavaScript 1.8.5 引入了該 Function.prototype.bind() 方法,該方法允許您指定應(yīng)該用于 this 給定函數(shù)的所有調(diào)用的值。這可以讓您輕松繞過(guò)不清楚會(huì)發(fā)生什么的問(wèn)題,具體取決于調(diào)用函數(shù)的上下文。另外,ES2015 支持箭頭函數(shù),如果我們?cè)?myArray 方法中,則可以使用詞法來(lái)編寫(xiě) setInterval(()=> this.myMethod)。
在需要很多定時(shí)器的頁(yè)面中,跟蹤所有正在運(yùn)行的定時(shí)器事件通常很困難。解決此問(wèn)題的一種方法是將有關(guān)計(jì)時(shí)器狀態(tài)的信息存儲(chǔ)在對(duì)象中。以下是這種抽象的最小例子。構(gòu)造函數(shù)體系結(jié)構(gòu)明確地避免了閉包的使用。它還提供了另一種將 this 對(duì)象傳遞給回調(diào)函數(shù)的方法(有關(guān)詳細(xì)信息,請(qǐng)參閱上文中的“this”問(wèn)題)。以下代碼也可在 GitHub 上獲得。
對(duì)于更復(fù)雜但仍然模塊化的版本(Daemon),請(qǐng)參閱 JavaScript 守護(hù)進(jìn)程管理。這個(gè)更復(fù)雜的版本不過(guò)是 Daemon 構(gòu)造函數(shù)的一個(gè)大而可擴(kuò)展的方法集合。然而,Daemon 構(gòu)造函數(shù)本身只不過(guò)是 MiniDaemon 的克隆,它在 Daemon 的實(shí)例化過(guò)程中增加了對(duì) init 和 onstart 函數(shù)的額外支持。所以這個(gè) MiniDaemon 框架仍然是簡(jiǎn)單動(dòng)畫(huà)的推薦方式,因?yàn)闆](méi)有其方法集合的 Daemon 實(shí)質(zhì)上是它的克隆。
/*\
|*|
|*| :: MiniDaemon ::
|*|
|*| Revision #2 - September 26, 2014
|*|
|*| https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval
|*| https://developer.mozilla.org/User:fusionchess
|*| https://github.com/madmurphy/minidaemon.js
|*|
|*| This framework is released under the GNU Lesser General Public License, version 3 or later.
|*| 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 = null;
MiniDaemon.prototype.task = null;
MiniDaemon.prototype.rate = 100;
MiniDaemon.prototype.length = Infinity;
/* These properties should be read-only */
MiniDaemon.prototype.SESSION = -1;
MiniDaemon.prototype.INDEX = 0;
MiniDaemon.prototype.PAUSED = true;
MiniDaemon.prototype.BACKW = true;
/* Global methods */
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;
};
/* Instances methods */
MiniDaemon.prototype.isAtEnd = function () {
return this.BACKW ? isFinite(this.length) && this.INDEX < 1 : this.INDEX + 1 > this.length;
};
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 將參數(shù)傳遞給回調(diào)函數(shù)。
如果您想使用本機(jī)不支持此功能的瀏覽器進(jìn)行操作,請(qǐng)使用上述建議的方法之一。
var myDaemon = new MiniDaemon(thisObject, callback[, rate[, length]]);
返回一個(gè) JavaScript 對(duì)象,其中包含動(dòng)畫(huà)所需的所有信息 (如此對(duì)象、回調(diào)函數(shù)、長(zhǎng)度、幀速率)。
thisObject
this
對(duì)象。它可以是一個(gè)或object
或 null
callback
Infinity
)和向后(backwards)(表示索引是增加還是減少的布爾值)。它類(lèi)似于 callback .call(thisObject,index,length,backwards)。如果回調(diào)函數(shù)返回一個(gè)false
值,則守護(hù)進(jìn)程(daemon)暫停。rate (optional)
length (optional)
Infinity
。默認(rèn)值是Infinity
。myDaemon.owner
this
對(duì)象(讀/寫(xiě))。它可以是一個(gè)object
或null
。myDaemon.task
Infinity
)和backwards(表示索引是否減少的布爾值) - 參見(jiàn)上文。如果該myDaemon.task
函數(shù)返回一個(gè)false
值,則守護(hù)進(jìn)程暫停。myDaemon.rate
myDaemon.length
Infinity
(讀/寫(xiě))。myDaemon.isAtEnd()
myDaemon.synchronize()
myDaemon.pause()
myDaemon.start([reverse])
MiniDaemon.forceCall(minidaemon)
INDEX
屬性都會(huì)增加/減少(取決于過(guò)程的實(shí)際方向)。您的HTML頁(yè)面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>MiniDaemin Example - MDN</title>
<script type="text/javascript" src="minidaemon.js"></script>
<style type="text/css">
#sample_div {
visibility: hidden;
}
</style>
</head>
<body>
<p>
<input type="button" onclick="fadeInOut.start(false /* optional */);" value="fade in" />
<input type="button" onclick="fadeInOut.start(true);" value="fade out">
<input type="button" onclick="fadeInOut.pause();" value="pause" />
</p>
<div id="sample_div">Some text here</div>
<script type="text/javascript">
function opacity (nIndex, nLength, bBackwards) {
this.style.opacity = nIndex / nLength;
if (bBackwards ? nIndex === 0 : nIndex === 1) {
this.style.visibility = bBackwards ? 'hidden' : 'visible';
}
}
var fadeInOut = new MiniDaemon(document.getElementById('sample_div'), opacity, 300, 8);
</script>
</body>
</html>
該 setInterval() 函數(shù)通常用于為一次又一次執(zhí)行的函數(shù)(例如動(dòng)畫(huà))設(shè)置延遲。
您可以使用 WindowOrWorkerGlobalScope.clearInterval() 取消間隔。
如果希望在指定的延遲后調(diào)用一次函數(shù),請(qǐng)使用 WindowOrWorkerGlobalScope.setTimeout()。
如果您的邏輯可能需要比間隔時(shí)間更長(zhǎng)的時(shí)間執(zhí)行,建議您使用 WindowOrWorkerGlobalScope.setTimeout 遞歸調(diào)用已命名的函數(shù)。例如,如果使用setInterval 每5秒輪詢(xún)一次遠(yuǎn)程服務(wù)器,網(wǎng)絡(luò)延遲,無(wú)響應(yīng)的服務(wù)器以及其他一系列問(wèn)題,可能會(huì)阻止請(qǐng)求在指定時(shí)間內(nèi)完成。因此,您可能會(huì)發(fā)現(xiàn)自己排隊(duì)等待XHR 請(qǐng)求,而這些請(qǐng)求不一定會(huì)按順序返回。
在這些情況下,遞歸 setTimeout() 模式是首選:
(function loop(){
setTimeout(function() {
// Your logic here
loop();
}, delay);
})();
在上面的代碼片段中,聲明了一個(gè)已命名的 loop() 函數(shù)并立即執(zhí)行。在邏輯完成執(zhí)行后 loop() 遞歸調(diào)用 setTimeout()。雖然這種模式不能保證在固定的時(shí)間間隔內(nèi)執(zhí)行,但它確實(shí)保證了在遞歸之前先前的時(shí)間間隔已經(jīng)完成。
setInterval () 在 Firefox 中受相同的節(jié)流限制 (setTimeout)。
規(guī)范 | 狀態(tài) | 注釋 |
---|---|---|
HTML Living Standard
在該規(guī)范中定義'WindowOrWorkerGlobalScope.setInterval()'。
|
Living Standard
|
方法轉(zhuǎn)移到最新規(guī)范中的WindowOrWorkerGlobalScope mixin。
|
HTML Living Standard
該規(guī)范中'WindowTimers.setInterval()'的定義。
|
Living Standard
|
初始定義(DOM Level 0) |
我們正在將兼容性數(shù)據(jù)轉(zhuǎn)換為機(jī)器可讀的JSON格式。
特征 | Chrome
|
Edge
|
Firefox(Gecko)[2]
|
Internet Explorer
|
Opera
|
Safari
|
---|---|---|---|---|---|---|
基本支持 | 支持:1.0 | 支持 | 支持:1.0(1.7或更早)、52[3] | 支持:4 | 支持:4 | 支持:1.0 |
支持回調(diào)參數(shù)[1] | 支持 | 支持 | 支持 | 支持:10.0 | 支持 | ? |
特征 | Android | Chrome for Android | Edge | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|---|
基本支持 | 支持:1.0 | 支持:1.0 | 支持 | 支持:1.0、52.0[3] | 支持:6.0 | 支持:6.0 | 支持:1.0 |
支持回調(diào)參數(shù)[1] | ? | ? | ? | ? | ? | ? | ? |
注釋?zhuān)?/p>
[1]它是否支持第一種形式的可選參數(shù)。
[2]在 Firefox 13之前,F(xiàn)irefox 向回調(diào)傳遞了一個(gè)額外的參數(shù),表明超時(shí)的“實(shí)際遲到”(以毫秒為單位)。從 Firefox 13 開(kāi)始不再提供此非標(biāo)準(zhǔn)參數(shù)。不建議基于 XPCOM 的 Firefox 擴(kuò)展使用 setInterval(),因?yàn)閿U(kuò)展更新代碼可能導(dǎo)致 Window 對(duì)象更新,從而丟失定時(shí)器。您應(yīng)該在 XPCOM 擴(kuò)展中應(yīng)改用 nsITimer。
[3] setInterval() 現(xiàn)在在 WindowOrWorkerGlobalScope mixin 上定義。
更多建議: