跳到主要内容

JavaScript 定时器

在Web开发中,我们经常需要延迟执行某些代码或定期重复执行某项任务。JavaScript提供了内置的定时器功能,帮助我们实现这些时间相关的操作。本文将介绍JavaScript中两种主要的定时器机制:setTimeoutsetInterval,以及它们的使用方法与应用场景。

什么是JavaScript定时器?

JavaScript定时器允许我们安排代码在未来某个时间点执行,或者按照固定的时间间隔重复执行。这些功能对于创建动画、延迟加载内容、轮询服务器、实现倒计时等场景非常有用。

JavaScript提供了两种主要的定时器函数:

  1. setTimeout() - 在指定的延迟后执行一次代码
  2. setInterval() - 按照指定的时间间隔重复执行代码

setTimeout() - 延时执行

setTimeout()函数用于在指定的毫秒数后执行一次特定的代码。

基本语法

javascript
let timerId = setTimeout(function/code, delay, param1, param2, ...);

参数说明:

  • function/code:要执行的函数或代码字符串(不推荐使用字符串)
  • delay:延迟的毫秒数(1000毫秒 = 1秒)
  • param1, param2, ...:(可选) 传递给函数的参数
  • 返回值:一个数值ID,可用于取消定时器

基本示例

javascript
// 基本用法
setTimeout(function() {
console.log("这段代码将在2秒后执行!");
}, 2000);

// 使用箭头函数
setTimeout(() => {
console.log("使用箭头函数的延时执行");
}, 1000);

// 传递参数
setTimeout((name) => {
console.log(`你好,${name}!`);
}, 1500, "小明");

// 输出:
// (1秒后) 使用箭头函数的延时执行
// (1.5秒后) 你好,小明!
// (2秒后) 这段代码将在2秒后执行!

取消定时器

如果你想在定时器触发前取消它,可以使用clearTimeout()函数:

javascript
// 设置定时器
const timerId = setTimeout(() => {
console.log("这段代码永远不会执行");
}, 3000);

// 取消定时器
clearTimeout(timerId);

setInterval() - 周期性执行

setInterval()函数用于按照指定的时间间隔重复执行代码。

基本语法

javascript
let intervalId = setInterval(function/code, delay, param1, param2, ...);

参数和setTimeout()相同,但行为不同 - setInterval会重复执行,直到被清除或页面关闭。

基本示例

javascript
// 每隔1秒执行一次
let counter = 0;
const intervalId = setInterval(() => {
counter++;
console.log(`计数: ${counter}`);

// 当计数达到5时停止
if (counter === 5) {
clearInterval(intervalId);
console.log("计数器已停止");
}
}, 1000);

// 输出:
// (1秒后) 计数: 1
// (2秒后) 计数: 2
// (3秒后) 计数: 3
// (4秒后) 计数: 4
// (5秒后) 计数: 5
// (5秒后) 计数器已停止

取消周期性定时器

setTimeout类似,我们可以使用clearInterval()函数取消周期性定时器:

javascript
const intervalId = setInterval(() => {
console.log("滴答");
}, 1000);

// 5秒后停止定时器
setTimeout(() => {
clearInterval(intervalId);
console.log("定时器已停止");
}, 5000);

定时器的注意事项

注意事项
  1. 定时器中的延迟时间并不精确,特别是当浏览器标签页不活跃或JavaScript引擎忙于执行其他代码时。
  2. 延迟时间为0的setTimeout不会立即执行,而是在当前执行栈清空后执行(通常是几毫秒后)。
  3. 在复杂应用中,未清除的定时器可能导致内存泄漏。

零延迟的setTimeout

setTimeout的一个常见用途是将代码推迟到当前执行栈清空后再执行:

javascript
setTimeout(() => {
console.log("C - 这句话虽然延迟为0,但会在当前执行栈清空后才执行");
}, 0);

console.log("A - 这句话先执行");
console.log("B - 这句话第二个执行");

// 输出:
// A - 这句话先执行
// B - 这句话第二个执行
// C - 这句话虽然延迟为0,但会在当前执行栈清空后才执行

定时器防抖与节流

在实际开发中,定时器常用于实现防抖(Debounce)和节流(Throttle)功能,这是处理高频事件的两种重要优化技术。

防抖(Debounce)

防抖的核心思想是:在事件被触发n秒后再执行回调,如果n秒内事件再次被触发,则重新计时。

javascript
function debounce(func, delay) {
let timerId;
return function(...args) {
// 如果已存在定时器则清除
clearTimeout(timerId);
// 设置新的定时器
timerId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}

// 使用示例:输入框搜索优化
const searchInput = document.getElementById('search-input');
const search = debounce(function(value) {
console.log(`搜索: ${value}`);
// 实际搜索操作...
}, 500);

searchInput.addEventListener('input', (e) => {
search(e.target.value);
});

节流(Throttle)

节流的核心思想是:在一段时间内,不管事件触发了多少次,只执行一次函数。

javascript
function throttle(func, delay) {
let lastCall = 0;
return function(...args) {
const now = new Date().getTime();
if (now - lastCall < delay) {
// 如果距离上次执行没有超过延迟时间,则不执行
return;
}
lastCall = now;
func.apply(this, args);
};
}

// 使用示例:滚动事件优化
const handleScroll = throttle(function() {
console.log("滚动中...");
// 实际滚动处理逻辑...
}, 200);

window.addEventListener('scroll', handleScroll);

实际应用案例

案例1:简单倒计时

创建一个10秒倒计时显示:

javascript
function startCountdown() {
let seconds = 10;

// 显示初始状态
document.getElementById('countdown').textContent = seconds;

const countdownInterval = setInterval(() => {
seconds--;
document.getElementById('countdown').textContent = seconds;

if (seconds <= 0) {
clearInterval(countdownInterval);
document.getElementById('countdown').textContent = "倒计时结束!";
}
}, 1000);
}

// HTML部分
// <div id="countdown">10</div>
// <button onclick="startCountdown()">开始倒计时</button>

案例2:图片轮播

使用定时器创建简单的图片轮播:

javascript
const images = [
'image1.jpg',
'image2.jpg',
'image3.jpg',
'image4.jpg'
];

let currentIndex = 0;
let slideshowInterval;

function startSlideshow() {
// 初始显示第一张图片
updateImage();

// 每3秒切换一次图片
slideshowInterval = setInterval(() => {
currentIndex = (currentIndex + 1) % images.length;
updateImage();
}, 3000);
}

function updateImage() {
document.getElementById('slideshow').src = images[currentIndex];
}

function stopSlideshow() {
clearInterval(slideshowInterval);
}

// HTML部分
// <img id="slideshow" src="image1.jpg" />
// <button onclick="startSlideshow()">开始轮播</button>
// <button onclick="stopSlideshow()">停止轮播</button>

案例3:打字机效果

使用定时器实现打字机效果:

javascript
function typeWriter(element, text, speed) {
let i = 0;

function type() {
if (i < text.length) {
element.innerHTML += text.charAt(i);
i++;
setTimeout(type, speed);
}
}

// 开始打字
element.innerHTML = '';
type();
}

// 使用示例
const textElement = document.getElementById('typing-text');
typeWriter(textElement, "欢迎学习JavaScript定时器!这是一个打字机效果示例...", 100);

// HTML部分
// <div id="typing-text"></div>

定时器与异步编程

虽然setTimeoutsetInterval可以用于处理异步操作,但在现代JavaScript中,我们通常更倾向于使用Promise和async/await进行复杂的异步操作。然而,了解定时器仍然很重要,因为它们构成了JavaScript异步编程的基础。

小贴士

在现代Web开发中,requestAnimationFrame通常是处理动画的更好选择,它会根据浏览器的重绘时机来调用回调函数,通常是60fps,并且在不可见的标签页中会自动暂停,节省资源。

总结

JavaScript定时器是处理时间相关操作的基础工具:

  1. setTimeout()可以在指定的延迟后执行一次函数
  2. setInterval()可以按照固定的时间间隔重复执行函数
  3. 使用clearTimeout()clearInterval()可以取消定时器
  4. 定时器广泛应用于动画、倒计时、轮播图、防抖节流等场景

熟练掌握定时器的使用,将有助于你开发更加动态和交互性强的Web应用。

练习题

  1. 创建一个数字时钟,在页面上显示当前时间,并每秒更新一次。
  2. 实现一个进度条,从0%到100%,每100毫秒增加1%。
  3. 创建一个简单的游戏,屏幕上有一个按钮,用户需要在按钮显示后的2秒内点击它,记录用户的反应时间。

更多学习资源