WindowOrWorkerGlobalScope接口方法:setInterval()

2018-03-28 10:58 更新

setInterval()方法

WindowOrWorkerGlobalScope mixin 的 setInterval() 方法反复调用一个函数或执行一个代码片段,每次调用之间有一个固定的时间延迟。它返回一个唯一标识时间间隔的 interval ID,以便稍后可以通过调用 clearInterval() 将其删除。这种方法在 Window 与 Worker 接口提供。

setInterval()方法语法

var intervalID = scope.setInterval(func,delay [,param1,param2,...]);
var intervalID = scope.setInterval(code,delay);

setInterval()方法参数

func
delay毫秒执行一次 function 。该函数不传递任何参数,并且没有返回值。
code
可选语法,允许您包含一个字符串,而不是每delay毫秒编译和执行的函数。不建议出于使用eval()安全风险的相同原因而使用此语法。
delay
以毫秒(千分之一秒)为单位的时间,计时器应延迟执行指定功能或代码之间的时间。如果此参数小于10,则使用值10。请注意,实际的延迟可能会更长。
param1, ..., paramN 可选的
一旦定时器到期,将传递给由 func 指定的函数其他参数。

注意:在 Internet Explorer 9 及更早版本中,以第一种语法向 setInterval() 传递附加参数不起作用。如果您想在该浏览器上启用此功能,则必须使用填充。

setInterval()方法返回值

返回值 intervalID 是一个非零的数值,用于标识由调用 setInterval() 创建的计时器;这个值可以传递给 WindowOrWorkerGlobalScope.clearInterval() 以取消超时。

了解 setInterval() 和 setTimeout() 共享相同的 ID 池可能会有所帮助,并且技术上可以互换使用 clearInterval() 和 clearTimeout() 可能会有帮助。但是,为了清晰起见,您应该尽量始终与它们匹配以避免在维护代码时出现混淆。

注意

:delay 参数被转换为有

符号的32位整数。这有效地限制 

delay 为2147483647毫秒,因为它在IDL中被指定为有符号整数。

setInterval()方法示例

示例1:基本语法

以下示例演示了setInterval()基本语法:

var intervalID = window.setInterval(myCallback, 500);

function myCallback() {
  // Your code here
}

例2:交替两种颜色

以下示例 flashtext() 每秒调用一次该功能,直到按下停止按钮:

<!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>

示例3:打字机模拟

以下示例首先清除打字机,然后将内容缓慢地键入与指定的一组选择器匹配的 NodeList 中,从而模拟打字机:

<!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 href="https://developer.mozilla.org/" rel="external nofollow" target="_blank"  target="_blank">Mozilla Developer Network</a></p>
<p id="controls" style="text-align: center;">[&nbsp;<span class="intLink" onclick="oTWExample1.play();">Play</span> | <span class="intLink" onclick="oTWExample1.pause();">Pause</span> | <span class="intLink" onclick="oTWExample1.terminate();">Terminate</span>&nbsp;]</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>

查看此演示中的操作。另见:clearInterval()。

回调参数

如前所述,Internet Explorer 9 和下面不支持将参数传递给 setTimeout () 或 setInterval () 中的回调函数。以下的 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;
}

另一种可能性是使用匿名函数来调用你的回调函数,虽然这个解决方案有点消耗。例:

var intervalID = setInterval(function() { myFunc('one', 'two', 'three'); }, 1000);

另一种可能性是使用函数的绑定,例如:

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)开始,间隔在非活动标签中被限制为每秒不超过一次。

“this”问题

当你传递一个方法到 setInterval() 或者其他函数时,它会被错误的 this 值调用。

说明

由 setInterval() 执行的代码在单独的执行上下文中运行,而不是调用它的函数。因此,被调用函数的 this 关键字被设置为 window(或 global)对象,它与调用 setTimeout 的函数的 this 值不同。看下面的例子(它用 setTimeout() 代替 setInterval(),这两个计时器的问题实际上是相同的):

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

正如你所看到的,没有办法将 this 对象传递给传统 JavaScript 中的回调函数。

可能的解决方案

解决这个 this 问题的一种可能的方法是,使用两个非本地的函数替换两个本地的 setTimeout() 或 setInterval() 全局函数,这两个函数通过该 Function.prototype.call 方法启用它们的调用。以下示例显示了可能的更换:

// 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);
};

这两个替代方案还使得 HTML5 标准可以将任意参数传递给IE中定时器的回调函数。

因此它们也可以用作非标准兼容的 polyfill。

新功能测试:

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

另一个更复杂的解决方案是以下框架。

JavaScript 1.8.5 引入了该 Function.prototype.bind() 方法,该方法允许您指定应该用于 this 给定函数的所有调用的值。这可以让您轻松绕过不清楚会发生什么的问题,具体取决于调用函数的上下文。另外,ES2015 支持箭头函数,如果我们在 myArray 方法中,则可以使用词法来编写 setInterval(()=> this.myMethod)。

MiniDaemon - 管理定时器的框架

在需要很多定时器的页面中,跟踪所有正在运行的定时器事件通常很困难。解决此问题的一种方法是将有关计时器状态的信息存储在对象中。以下是这种抽象的最小例子。构造函数体系结构明确地避免了闭包的使用。它还提供了另一种将 this 对象传递给回调函数的方法(有关详细信息,请参阅上文中的“this”问题)。以下代码也可在 GitHub 上获得。

对于更复杂但仍然模块化的版本(Daemon),请参阅 JavaScript 守护进程管理。这个更复杂的版本不过是 Daemon 构造函数的一个大而可扩展的方法集合。然而,Daemon 构造函数本身只不过是 MiniDaemon 的克隆,它在 Daemon 的实例化过程中增加了对 init 和 onstart 函数的额外支持。所以这个 MiniDaemon 框架仍然是简单动画的推荐方式,因为没有其方法集合的 Daemon 实质上是它的克隆。

minidaemon.js

/*\
|*|
|*|  :: 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 将参数传递给回调函数。

如果您想使用本机不支持此功能的浏览器进行操作,请使用上述建议的方法之一。

MiniDaemon句法

var myDaemon = new MiniDaemon(thisObject, callback[, rate[, length]]);

描述

返回一个 JavaScript 对象,其中包含动画所需的所有信息 (如此对象、回调函数、长度、帧速率)。

参数

thisObject
调用回调函数的this对象。它可以是一个或object或 null
callback
重复调用的函数。它有三个参数调用:索引(index)(每个调用的迭代索引);长度(length)(分配给守护进程的总调用数- 有限或Infinity)和向后(backwards)(表示索引是增加还是减少的布尔值)。它类似于 callback .call(thisObject,index,length,backwards)。如果回调函数返回一个false值,则守护进程(daemon)暂停
rate (optional)
每次调用之间的时间间隔(以毫秒为单位)。默认值是100。
length (optional)
调用的总数。它可以是一个正整数或Infinity。默认值是Infinity

MiniDaemon 实例属性

myDaemon.owner
执行守护进程的this对象(读/写)。它可以是一个objectnull
myDaemon.task
重复调用的函数(读/写)。它有三个参数调用:index(每个调用的迭代索引),length(分配给守护进程的总调用数 - 有限或Infinity)和backwards(表示索引是否减少的布尔值) - 参见上文。如果该myDaemon.task函数返回一个false值,则守护进程暂停。
myDaemon.rate
每次调用(读/写)之间的时间间隔(以毫秒为单位)。
myDaemon.length
调用的总数。它可以是一个正整数或Infinity(读/写)。

MiniDaemon 实例方法

myDaemon.isAtEnd()
返回表示守护进程是否在开始/结束位置的布尔值。
myDaemon.synchronize()
将启动的守护进程的定时器与其调用时间同步。
myDaemon.pause()
暂停守护进程。
myDaemon.start([reverse])
启动后台进程(每个调用的索引增加)或向后(索引减少)。

MiniDaemon 全局对象方法

MiniDaemon.forceCall(minidaemon)
无论结束是否已到达,强制对 minidaemon.task 函数进行单个回调。在任何情况下,内部INDEX属性都会增加/减少(取决于过程的实际方向)。

用法示例

您的HTML页面:

<!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()方法笔记

该 setInterval() 函数通常用于为一次又一次执行的函数(例如动画)设置延迟。

您可以使用 WindowOrWorkerGlobalScope.clearInterval() 取消间隔。

如果希望在指定的延迟后调用一次函数,请使用 WindowOrWorkerGlobalScope.setTimeout()。

确保执行时间短于间隔频率

如果您的逻辑可能需要比间隔时间更长的时间执行,建议您使用 WindowOrWorkerGlobalScope.setTimeout 递归调用已命名的函数。例如,如果使用setInterval 每5秒轮询一次远程服务器,网络延迟,无响应的服务器以及其他一系列问题,可能会阻止请求在指定时间内完成。因此,您可能会发现自己排队等待XHR 请求,而这些请求不一定会按顺序返回。

在这些情况下,递归 setTimeout() 模式是首选:

(function loop(){
   setTimeout(function() {
      // Your logic here

      loop();
  }, delay);
})();

在上面的代码片段中,声明了一个已命名的 loop() 函数并立即执行。在逻辑完成执行后 loop() 递归调用 setTimeout()。虽然这种模式不能保证在固定的时间间隔内执行,但它确实保证了在递归之前先前的时间间隔已经完成。

限制间隔

setInterval () 在 Firefox 中受相同的节流限制 (setTimeout)。

规范

规范 状态 注释
HTML Living Standard 
在该规范中定义'WindowOrWorkerGlobalScope.setInterval()'。
Living Standard
方法转移到最新规范中的WindowOrWorkerGlobalScopemixin。
HTML Living Standard 
规范中'WindowTimers.setInterval()'的定义。
Living Standard
初始定义(DOM Level 0)

浏览器兼容性

我们正在将兼容性数据转换为机器可读的JSON格式。

  • 电脑端
特征 Chrome
Edge
Firefox(Gecko)[2]
Internet Explorer
Opera
Safari
基本支持 支持:1.0 支持 支持:1.0(1.7或更早)、52[3] 支持:4 支持:4 支持:1.0
支持回调参数[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
支持回调参数[1] ? ? ? ? ? ? ?

注释:

[1]它是否支持第一种形式的可选参数。

[2]在 Firefox 13之前,Firefox 向回调传递了一个额外的参数,表明超时的“实际迟到”(以毫秒为单位)。从 Firefox 13 开始不再提供此非标准参数。不建议基于 XPCOM 的 Firefox 扩展使用 setInterval(),因为扩展更新代码可能导致 Window 对象更新,从而丢失定时器。您应该在 XPCOM 扩展中应改用 nsITimer。

[3] setInterval() 现在在 WindowOrWorkerGlobalScope mixin 上定义。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号