setInterval() 全局函数
注意:此功能在Web Workers中可用。
setInterval() 方法在 Window 和 WorkerGlobalScope 接口上提供,它以固定的时间延迟重复调用函数或执行代码片段。
此方法返回一个间隔 ID,该 ID 唯一标识间隔,因此您可以稍后通过调用 clearInterval() 来将其删除。
语法
setInterval(code)
setInterval(code, delay)
setInterval(func)
setInterval(func, delay)
setInterval(func, delay, arg1)
setInterval(func, delay, arg1, arg2)
setInterval(func, delay, arg1, arg2, /* …, */ argN)
参数
返回值
返回的 intervalID 是一个数字的非零值,它标识由调用 setInterval() 创建的定时器;此值可以传递给 clearInterval() 以取消间隔。
了解 setInterval() 和 setTimeout() 共享相同的 ID 池,并且 clearInterval() 和 clearTimeout() 在技术上可以互换使用,这一点可能会有所帮助。但是,为了清晰起见,您应该尽量始终使它们匹配,以避免在维护代码时产生混淆。
注意:delay 参数被转换为带符号的 32 位整数。由于它在 IDL 中被指定为带符号整数,因此这实际上将 delay 限制为 2147483647 毫秒(大约 24.8 天)。
示例
示例 1:基本语法
以下示例演示了 setInterval() 的基本语法。
const intervalID = setInterval(myCallback, 500, "Parameter 1", "Parameter 2");
function myCallback(a, b) {
// Your code here
// Parameters are purely optional.
console.log(a);
console.log(b);
}
示例 2:交替两种颜色
以下示例每秒调用一次 flashtext() 函数,直到按下“停止”按钮。
HTML
<div id="my_box">
<h3>Hello World</h3>
</div>
<button id="start">Start</button>
<button id="stop">Stop</button>
CSS
.go {
color: green;
}
.stop {
color: red;
}
JavaScript
// variable to store our intervalID
let nIntervId;
function changeColor() {
// check if an interval has already been set up
if (!nIntervId) {
nIntervId = setInterval(flashText, 1000);
}
}
function flashText() {
const oElem = document.getElementById("my_box");
oElem.className = oElem.className === "go" ? "stop" : "go";
}
function stopTextColor() {
clearInterval(nIntervId);
// release our intervalID from the variable
nIntervId = null;
}
document.getElementById("start").addEventListener("click", changeColor);
document.getElementById("stop").addEventListener("click", stopTextColor);
结果
另请参阅:clearInterval()。
“this” 问题
当您将方法传递给 setInterval() 或任何其他函数时,它将使用错误的 this 值被调用。此问题在 JavaScript 参考中进行了详细解释。
说明
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
如您所见,在旧版 JavaScript 中没有方法将 this 对象传递给回调函数。
可能的解决方案
所有现代 JavaScript 运行时(在浏览器和其他地方)都支持 箭头函数,以及词法 this - 如果我们在 myArray 方法内部,则允许我们编写 setInterval(() => this.myMethod())。
如果您需要支持 IE,请使用 Function.prototype.bind() 方法,该方法允许您指定应作为给定函数的所有调用的 this 使用的值。这样可以轻松避免在不清楚 this 将是什么的情况下出现问题,具体取决于调用函数的上下文。
使用说明
setInterval() 函数通常用于为重复执行的函数(例如动画)设置延迟。您可以使用 clearInterval() 取消间隔。
如果您希望在指定的延迟后只调用一次函数,请使用 setTimeout()。
延迟限制
间隔可以嵌套;也就是说,setInterval() 的回调可以依次调用 setInterval() 以启动另一个间隔运行,即使第一个间隔仍在运行。为了减轻这可能对性能产生的潜在影响,一旦间隔嵌套超过五层,浏览器将自动强制执行 4 毫秒的最小值。在深度嵌套的 setInterval() 调用中尝试指定小于 4 毫秒的值将被固定为 4 毫秒。
在某些情况下,浏览器可能会强制执行更严格的间隔最小值,尽管这些情况应该不常见。还要注意,回调调用之间实际经过的时间可能比给定的 delay 更长;请参阅指定延迟时间过长原因以获取示例。
确保执行持续时间短于间隔频率
如果您的逻辑可能需要比间隔时间更长的时间才能执行,建议您使用 setTimeout() 递归调用命名函数。例如,如果使用 setInterval() 每 5 秒轮询远程服务器一次,则网络延迟、服务器无响应以及许多其他问题可能会阻止请求在分配的时间内完成。因此,您可能会发现自己拥有排队的 XHR 请求,这些请求不一定会按顺序返回。
在这些情况下,首选递归 setTimeout() 模式
(function loop() {
setTimeout(() => {
// Your logic here
loop();
}, delay);
})();
在上面的代码片段中,声明了一个命名函数 loop() 并立即执行。在逻辑执行完成后,loop() 在 setTimeout() 中递归调用。虽然此模式不能保证以固定间隔执行,但它确实保证了在递归之前先完成先前的间隔。
规范
| 规范 |
|---|
| HTML 标准 # dom-setinterval-dev |
浏览器兼容性
BCD 表格仅在浏览器中加载