使用JS實(shí)現(xiàn)一個(gè)高精準(zhǔn)定時(shí)器和延時(shí)器
一、為什么瀏覽器定時(shí)器不精準(zhǔn)?
1?? JS 是單線程
- 主線程被占用 → 定時(shí)器回調(diào)延遲
- UI / 渲染 / GC 都會(huì)阻塞
2?? 瀏覽器最小時(shí)間精度限制
- HTML5 規(guī)范限制(4ms)
- 后臺(tái) Tab 被強(qiáng)制降頻(1000ms+)
3?? 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)
- 不是簡單等待 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 | 很高 | 長期計(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í)間同步。
以上就是使用JS實(shí)現(xiàn)一個(gè)高精準(zhǔn)定時(shí)器和延時(shí)器的詳細(xì)內(nèi)容,更多關(guān)于JS實(shí)現(xiàn)定時(shí)器和延時(shí)器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
學(xué)習(xí)JSON.stringify的9大特性和轉(zhuǎn)換規(guī)則
本文介紹JSON.stringify9大特性和轉(zhuǎn)換規(guī)則,JSON.stringify()方法將一個(gè)JavaScript對(duì)象或值轉(zhuǎn)換為?JSON?字符串,如果指定了一個(gè)replacer?函數(shù),則可以選擇性地替換值,或者指定的replacer是數(shù)組,則可選擇性地僅包含數(shù)組指定的屬性,更多內(nèi)容需要的小火煸可以參考下面溫行內(nèi)容2022-02-02
Promise.race和Promise.any使用示例詳解
這篇文章主要為大家介紹了如何使用Promise.race() 和 Promise.any() 示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
javascript字符串與數(shù)組轉(zhuǎn)換匯總
本文給大家分享的是Js中字符串轉(zhuǎn)換成數(shù)組,數(shù)組轉(zhuǎn)換成字符串的函數(shù),十分的簡單實(shí)用,有需要的小伙伴可以參考下。2015-05-05
javascript模擬實(shí)現(xiàn)C# String.format函數(shù)功能代碼
這篇文章主要介紹了javascript模擬實(shí)現(xiàn)C# String.format函數(shù)功能,相信大家可以用的到2013-11-11
js中substring和substr兩者區(qū)別和使用方法
這篇文章主要介紹了js中substring和substr兩者區(qū)別和使用方法,每一個(gè)步驟都有相應(yīng)的文字介紹,感興趣的小伙伴們可以參考一下2015-11-11
js,jq,css多方面實(shí)現(xiàn)簡易下拉菜單功能
這篇文章主要介紹了js,jq,css多方面實(shí)現(xiàn)簡易下拉菜單功能,需要的朋友可以參考下2017-05-05

