js实现计时器效果
使用 setTimeout 实现单次计时器
通过 setTimeout 可以创建一个在指定时间后执行的单次计时器:
function delayedAlert() {
console.log('3秒后执行');
}
setTimeout(delayedAlert, 3000);
使用 setInterval 实现循环计时器
setInterval 会按照固定时间间隔重复执行代码:
let counter = 0;
const intervalId = setInterval(() => {
counter++;
console.log(`已执行 ${counter} 次`);
if(counter >= 5) {
clearInterval(intervalId);
}
}, 1000);
使用 requestAnimationFrame 实现动画计时器
对于需要与屏幕刷新率同步的动画效果,推荐使用 requestAnimationFrame:
let startTime = null;
function animate(timestamp) {
if (!startTime) startTime = timestamp;
const elapsed = timestamp - startTime;
console.log(`已运行 ${elapsed} 毫秒`);
if (elapsed < 2000) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
实现可暂停的计时器
通过组合 Date 对象和 setTimeout 可以实现可暂停的计时器:
class Timer {
constructor() {
this.startTime = 0;
this.elapsed = 0;
this.timerId = null;
}
start() {
this.startTime = Date.now() - this.elapsed;
this.timerId = setInterval(() => {
this.elapsed = Date.now() - this.startTime;
console.log(`已运行: ${this.elapsed}ms`);
}, 100);
}
pause() {
clearInterval(this.timerId);
}
reset() {
clearInterval(this.timerId);
this.elapsed = 0;
console.log('计时器已重置');
}
}
const timer = new Timer();
timer.start();
实现倒计时功能
倒计时器可以通过计算剩余时间来实现:
function countdown(seconds) {
const intervalId = setInterval(() => {
console.log(`剩余: ${seconds}秒`);
seconds--;
if(seconds < 0) {
clearInterval(intervalId);
console.log('倒计时结束');
}
}, 1000);
}
countdown(10);
使用性能计时 API
对于需要高精度计时的场景,可以使用 performance.now():
const start = performance.now();
// 执行一些操作
for(let i=0; i<1000000; i++) {}
const end = performance.now();
console.log(`耗时: ${end - start} 毫秒`);
计时器精度问题处理
JavaScript 计时器的最小延迟通常为4ms,且会受到浏览器标签页状态影响。对于需要精确计时的场景:
function highPrecisionTimer(callback, interval) {
let expected = performance.now() + interval;
let timeoutId;
function tick() {
const drift = performance.now() - expected;
callback();
expected += interval;
timeoutId = setTimeout(tick, Math.max(0, interval - drift));
}
timeoutId = setTimeout(tick, interval);
return {
clear: () => clearTimeout(timeoutId)
};
}
const timer = highPrecisionTimer(() => {
console.log('高精度计时');
}, 1000);
Web Worker 实现后台计时
为了避免主线程阻塞影响计时精度,可以使用 Web Worker:
worker.js:
let intervalId;
self.onmessage = function(e) {
if(e.data.command === 'start') {
let counter = 0;
intervalId = setInterval(() => {
counter++;
self.postMessage(counter);
}, 1000);
} else if(e.data.command === 'stop') {
clearInterval(intervalId);
}
};
主线程:

const worker = new Worker('worker.js');
worker.onmessage = function(e) {
console.log(`计时: ${e.data}秒`);
};
worker.postMessage({command: 'start'});






