前端實(shí)現(xiàn)一個(gè)高精準(zhǔn)定時(shí)器和延時(shí)器的完整代碼
一、為什么瀏覽器定時(shí)器不精準(zhǔn)?
JS 是單線程
- 主線程被占用 → 定時(shí)器回調(diào)延遲
- UI / 渲染 / GC 都會(huì)阻塞
瀏覽器最小時(shí)間精度限制
- HTML5 規(guī)范限制(4ms)
- 后臺(tái) Tab 被強(qiáng)制降頻(1000ms+)
setInterval 的“時(shí)間漂移”
setInterval(fn, 1000); // 實(shí)際執(zhí)行時(shí)間 = 1000 + fn執(zhí)行時(shí)間
?? 時(shí)間會(huì)越來越不準(zhǔn)
二、高精準(zhǔn)定時(shí)器的核心思想(先記?。?/h2>
不用“執(zhí)行次數(shù)”計(jì)時(shí),而用“時(shí)間戳”對(duì)齊真實(shí)時(shí)間。
不用“執(zhí)行次數(shù)”計(jì)時(shí),而用“時(shí)間戳”對(duì)齊真實(shí)時(shí)間。
三、高精準(zhǔn)延時(shí)器(setTimeout 替代方案)
實(shí)現(xiàn):時(shí)間戳校正法
function preciseTimeout(fn, delay) {
const start = performance.now();
function loop() {
const now = performance.now();
if (now - start >= delay) {
fn();
} else {
requestAnimationFrame(loop);
}
}
loop();
}
為什么準(zhǔn)?
- 使用高精度時(shí)鐘
performance.now() - 每幀校正誤差
四、高精準(zhǔn)定時(shí)器(setInterval 替代方案)
實(shí)現(xiàn):遞歸 setTimeout + 時(shí)間修正
function preciseInterval(fn, interval) {
let expected = performance.now() + interval;
function step() {
const drift = performance.now() - expected;
fn();
expected += interval;
setTimeout(step, Math.max(0, interval - drift));
}
setTimeout(step, interval);
}
核心點(diǎn)
- 不是簡(jiǎn)單等待 interval
- 每次都修正漂移
五、Web Worker 定時(shí)器(更準(zhǔn))
為什么 Worker 更準(zhǔn)?
- 不阻塞 UI 線程
- 不受頁面渲染影響
worker.js
setInterval(() => {
postMessage(Date.now());
}, 1000);
主線程
const worker = new Worker('worker.js');
worker.onmessage = () => {
console.log('tick');
};
?? 計(jì)時(shí)類、音頻、監(jiān)控系統(tǒng)首選
六、requestAnimationFrame 方案(適合動(dòng)畫)
let last = performance.now();
function rafTimer() {
const now = performance.now();
if (now - last >= 1000) {
console.log('tick');
last = now;
}
requestAnimationFrame(rafTimer);
}
rafTimer();
七、三種方案對(duì)比(面試必背)
| 方案 | 精度 | 適合場(chǎng)景 |
|---|---|---|
| setTimeout | 低 | 普通任務(wù) |
| 時(shí)間校正 | 高 | 業(yè)務(wù)定時(shí) |
| Web Worker | 很高 | 長(zhǎng)期計(jì)時(shí) |
| RAF | 高 | 動(dòng)畫 / UI |
八、延時(shí)器 vs 定時(shí)器(概念區(qū)分)
| 類型 | 特點(diǎn) |
|---|---|
| 延時(shí)器 | 執(zhí)行一次 |
| 定時(shí)器 | 周期執(zhí)行 |
| 高精準(zhǔn) | 基于時(shí)間差 |
九、后臺(tái) / 鎖屏問題(高級(jí))
問題
- 瀏覽器后臺(tái) Tab 會(huì)降頻
解決方案
- Web Worker
- Visibility API + 校正
- 服務(wù)端時(shí)間對(duì)齊
十、30 秒面試標(biāo)準(zhǔn)回答(直接背)
瀏覽器原生定時(shí)器會(huì)因主線程阻塞產(chǎn)生時(shí)間漂移;
高精準(zhǔn)定時(shí)器應(yīng)基于時(shí)間戳校正,而不是固定間隔;
可以通過遞歸 setTimeout、requestAnimationFrame 或 Web Worker 提升精度;
對(duì)精度要求極高的場(chǎng)景應(yīng)使用 Worker 或服務(wù)端時(shí)間同步。
到此這篇關(guān)于前端實(shí)現(xiàn)一個(gè)高精準(zhǔn)定時(shí)器和延時(shí)器的文章就介紹到這了,更多相關(guān)前端實(shí)現(xiàn)定時(shí)器和延時(shí)器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
TypeScript 中的可辨識(shí)聯(lián)合(Discriminated Unions)設(shè)計(jì)模式
TypeScript的可辨識(shí)聯(lián)合(Discriminated Unions)是一種結(jié)合聯(lián)合類型和字面量類型的設(shè)計(jì)模式,用于安全處理多種數(shù)據(jù)類型,本文就來詳細(xì)的介紹一下TypeScript可辨識(shí)聯(lián)合的使用,感興趣的可以了解一下2026-05-05
JavaScript前后端數(shù)據(jù)交互工具ajax使用教程
Ajax(Asynchronous?Javascript?And?XML),即是異步的JavaScript和XML,Ajax其實(shí)就是瀏覽器與服務(wù)器之間的一種異步通信方式2022-10-10
微信小程序開發(fā)教程-手勢(shì)解鎖實(shí)例
手勢(shì)解鎖是app上常見的解鎖方式,相比輸入密碼方式操作起來要方便許多。這篇文章主要介紹了微信小程序開發(fā)教程-手勢(shì)解鎖實(shí)例,有興趣的可以了解一下。2017-01-01
TypeScript中的互斥類型實(shí)現(xiàn)方法示例
用了一年時(shí)間的TypeScript了,下面這篇文章主要給大家介紹了關(guān)于TypeScript中互斥類型實(shí)現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04
JS+CSS實(shí)現(xiàn)的經(jīng)典tab選項(xiàng)卡效果代碼
這篇文章主要介紹了JS+CSS實(shí)現(xiàn)的經(jīng)典tab選項(xiàng)卡效果代碼,通過簡(jiǎn)單的鼠標(biāo)事件觸發(fā)js函數(shù)實(shí)現(xiàn)針對(duì)頁面元素的遍歷與樣式變換功能,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09
JavaScript撤銷恢復(fù)操作的實(shí)現(xiàn)方法詳解
這篇文章主要介紹了JavaScript撤銷恢復(fù)操作的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-02-02

