1. setInterval()
:周期性执行函数
setInterval()
会按照指定的时间间隔(毫秒)重复执行一个函数,直到被手动停止。
基本语法:
const intervalId = setInterval(callback, delay, [arg1, arg2, ...]);
callback
:要执行的函数。delay
:每次执行的间隔时间(毫秒)。arg1, arg2, ...
:可选参数,传递给callback
的参数。
示例:每秒更新时钟
function updateClock() {
const now = new Date();
console.log(now.toLocaleTimeString());
}
// 每1000毫秒(1秒)执行一次
const intervalId = setInterval(updateClock, 1000);
// 5秒后停止
setTimeout(() => {
clearInterval(intervalId); // 清除定时器
}, 5000);
2. setTimeout()
:延迟执行函数
setTimeout()
会在指定的延迟时间(毫秒)后执行一次函数。
基本语法:
const timeoutId = setTimeout(callback, delay, [arg1, arg2, ...]);
参数含义与 setInterval()
相同。
示例:延迟提示
function showMessage() {
alert('3秒后显示此消息');
}
// 3000毫秒(3秒)后执行
setTimeout(showMessage, 3000);
3. 清除定时器
为避免内存泄漏或不必要的执行,需要在适当的时候清除定时器:
清除 setInterval()
:
const intervalId = setInterval(() => { /* 代码 */ }, 1000);
clearInterval(intervalId); // 停止循环执行
清除 setTimeout()
:
const timeoutId = setTimeout(() => { /* 代码 */ }, 1000);
clearTimeout(timeoutId); // 取消延迟执行
4. 应用场景
(1)轮询数据
定期从服务器获取更新:
function fetchData() {
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data));
}
// 每5秒请求一次
setInterval(fetchData, 5000);
(2)实现动画效果
通过微小间隔更新元素样式:
const element = document.getElementById('box');
let position = 0;
function move() {
position += 1;
element.style.left = `${position}px`;
}
// 每16毫秒(约60FPS)更新一次位置
setInterval(move, 16);
(3)延迟加载资源
// 页面加载后3秒加载广告脚本
setTimeout(() => {
const script = document.createElement('script');
script.src = 'ad.js';
document.body.appendChild(script);
}, 3000);
5. 注意事项
(1)时间精度问题
- JavaScript 是单线程的,定时器的执行时间可能会受到其他任务的影响,实际延迟可能比设定值长。
(2)闭包陷阱
- 定时器中的回调函数会捕获外部变量,可能导致意外结果:
for (var i = 0; i < 5; i++) { setTimeout(() => { console.log(i); // 输出5,5,5,5,5 }, 1000); } // 使用let(块级作用域)或立即执行函数解决 for (let i = 0; i < 5; i++) { setTimeout(() => { console.log(i); // 输出0,1,2,3,4 }, 1000); }
(3)内存泄漏风险
- 未清除的定时器会持续占用内存,特别是在单页应用(SPA)中切换页面时。
6. 替代方案
(1)requestAnimationFrame()
更适合高性能动画,由浏览器优化执行时机:
function animate() {
// 更新动画
requestAnimationFrame(animate); // 递归调用
}
requestAnimationFrame(animate);
(2)Promise
+ setTimeout
实现可暂停、可链式调用的延迟:
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 使用示例
async function fetchWithRetry() {
try {
const response = await fetch('/api/data');
return response.json();
} catch (error) {
await delay(2000); // 等待2秒后重试
return fetchWithRetry();
}
}