偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

還在用 SetInterval?定時器翻車了......

開發(fā) 前端
當主線程正在執(zhí)行某段耗時操作(比如大數(shù)據(jù)計算、復雜 DOM 渲染),定時器即使“到點了”,也得乖乖排隊,等前面的任務(wù)執(zhí)行完再說。

前端開發(fā)中,有一個 API 幾乎所有同學都用過,那就是:setInterval

很多同學會使用它完成各種功能,比如:輪播圖、定時任務(wù),甚至有些同學會用它控制動畫等等的。

但是,但是,問題來了。。。

真實場景

1. 跳秒問題

當我們在使用setInterval 做定時任務(wù),頁面切出去,再切回來,可能會出現(xiàn)“跳秒” 的問題。

看一個真實場景。

比如咱們現(xiàn)在要做一個 倒計時 或 定時任務(wù),參考以下代碼:

setInterval(() => {
  leftTime--
  updateUI(leftTime)
}, 1000)

邏輯很簡單:每隔 1 秒執(zhí)行一次,倒計時減 1。

在實驗環(huán)境下測試完全沒問題,但上線后就很容易出事。

比如:用戶在支付頁面等待時,臨時切出去看了條微信消息,等他切回來的時候,倒計時瞬間“咔咔咔”跳了好幾秒。更嚴重的是,還很有可能出現(xiàn):頁面還顯示“剩余 10 秒”,但后端已經(jīng)判定超時,導致支付失敗。

為什么會這樣呢?

這是因為 瀏覽器在頁面切到后臺時,會對定時器做“節(jié)流”甚至“掛起”處理,Chrome 會把定時器最小間隔限制到 1000ms,甚至直接暫停,等用戶切回來時,所有延遲的回調(diào)會一股腦兒執(zhí)行,造成倒計時猛跳。

于是,用戶看到的時間和真實時間就徹底錯亂了。

2. 動畫卡頓問題

很多同學在寫動畫時,都會直接用 setInterval 來驅(qū)動,比如:

setInterval(() => {
  box.style.left = box.offsetLeft + 5 + 'px'
}, 16) // 約等于 60 FPS

理論上 16ms 一次,剛好能模擬出 60 幀的絲滑效果。

但上線后,用戶體驗卻完全不是這么回事:

一旦瀏覽器線程稍微繁忙(例如頁面里還有圖片加載、腳本計算),定時器就不可能按時觸發(fā),16ms 可能拖成 30ms、50ms,甚至更長。

這就回導致,動畫本來應(yīng)該流暢平移,但實際看起來就是一頓一頓的,像是在“丟幀”一樣。如果動畫持續(xù)時間比較長,抖動感會越來越明顯。

更坑的是,setInterval 的調(diào)度是不和瀏覽器的 渲染節(jié)奏 對齊的。

換句話說,它根本不知道什么時候瀏覽器會重繪,于是就可能在屏幕還沒準備好的時候強行更新 DOM,結(jié)果就是:CPU 忙,動畫抖,用戶體驗一塌糊涂。

這就是為什么在做動畫時,很多大廠前端幾乎不會再用 setInterval,而是推薦 requestAnimationFrame !這是因為,它能跟隨瀏覽器的刷新節(jié)奏來執(zhí)行,動畫才真正絲滑。

3. 內(nèi)存溢出與邏輯錯亂

在實際項目里,很多同學用 setInterval 做 輪詢請求 或者 周期任務(wù),但往往忽略了一個細節(jié):清理。

舉個例子:在一個管理后臺里,你需要每隔 5 秒請求一次接口,刷新任務(wù)列表:

setInterval(() => {
  fetch('/api/sunday/status')
    .then(res => res.json())
    .then(updateUI)
}, 5000)

看起來沒啥問題,但真實業(yè)務(wù)中很容易出現(xiàn)以下情況:

  • 重復觸發(fā): 頁面上有多個入口會初始化這段邏輯,結(jié)果一個頁面里開了 3、4 個定時器,都在請求同一個接口。 后端壓力飆升,前端控制臺瘋狂打印日志,CPU 占用直線拉升。
  • 忘記清理: 用戶從 A 頁面跳到 B 頁面,A 頁面的定時器還在跑。 當用戶連續(xù)操作幾個頁面時,定時器越積越多,最后導致 邏輯錯亂 + 內(nèi)存暴漲。
  • 級聯(lián) Bug: 有一次,開發(fā)同學在組件 mounted 里寫了 setInterval,卻忘了在 unmounted 里清理。 結(jié)果用戶在頁面里反復切換模塊,幾十個定時器同時在跑,接口請求量暴增,頁面直接卡死。

這類問題往往很隱蔽,開發(fā)環(huán)境下測試不出來,但一旦上線,就會引發(fā)性能問題甚至內(nèi)存泄漏,屬于那種“天坑選手”。

為什么這些問題會發(fā)生?

要搞清楚 setInterval 為什么容易翻車,先得明白它背后的運行機制。

1. JS 是單線程的

瀏覽器里的 JavaScript 引擎,是單線程的。這意味著:同一時間只能做一件事。

當主線程正在執(zhí)行某段耗時操作(比如大數(shù)據(jù)計算、復雜 DOM 渲染),定時器即使“到點了”,也得乖乖排隊,等前面的任務(wù)執(zhí)行完再說。

結(jié)果就是:延遲疊加 → 執(zhí)行不準。

2. 定時器屬于宏任務(wù)

在事件循環(huán)(Event Loop)機制里:

  • setInterval 和 setTimeout 的回調(diào),都會被放進 宏任務(wù)隊列;
  • 宏任務(wù)只有在當前調(diào)用棧清空之后,才會被執(zhí)行。

所以,即便你寫了 setInterval(fn, 1000),并不意味著它會精確地每隔 1000ms 執(zhí)行。

真實情況更像是:至少 1000ms 后,再加上隊列排隊的時間。一旦頁面繁忙,定時器就會嚴重“拖堂”。

3. 瀏覽器對后臺頁面的“節(jié)流”

為了省電、省性能,現(xiàn)代瀏覽器會對不在前臺激活的頁面做限制:

  • Chrome 最小間隔強制拉到 1000ms;
  • 有時候甚至直接掛起定時器。

這就解釋了為什么頁面切出去再回來時,倒計時會“咔咔咔”跳秒。

4. 定時器堆積效應(yīng)

setInterval 有一個“坑”,那就是:如果你的回調(diào)函數(shù)執(zhí)行時間 大于間隔時間,新的任務(wù)依然會不斷加入隊列。

所以,setInterval 最大的問題就在于:它不是一個精準的“時鐘”,而是一個“排隊觸發(fā)器”。

在空閑時,它挺準;一旦頁面復雜、線程繁忙、切換后臺,問題就接連出現(xiàn)。

終極解決方案

那么,既然 setInterval 這么“不靠譜”,那我們該怎么辦?

其實,針對不同的場景,有幾種更好的替代方案。

1. 動畫場景 → 用 requestAnimationFrame

動畫的核心問題是:幀率要跟上瀏覽器的刷新節(jié)奏。

  • setInterval(fn, 16) 只是“猜”瀏覽器 60Hz,完全沒同步到真正的刷新。
  • 而 requestAnimationFrame(簡稱 rAF),會在 瀏覽器即將重繪前 執(zhí)行回調(diào),保證動畫和渲染對齊。
function move() {
  box.style.left = box.offsetLeft + 5 + 'px'
  requestAnimationFrame(move)
}

requestAnimationFrame(move)

2. 倒計時場景 → 基于時間戳校正

定時任務(wù)真正關(guān)心的不是“回調(diào)執(zhí)行了幾次”,而是 當前時間與目標時間的差值。

所以更靠譜的做法是:用 Date.now() 或 performance.now() 來校正。

const end = Date.now() + 15 * 60 * 1000 // 15分鐘后
const timer = setInterval(() => {
  const diff = end - Date.now()
  if (diff <= 0) {
    clearInterval(timer)
    console.log('倒計時結(jié)束')
  } else {
    console.log('剩余秒數(shù):', Math.floor(diff / 1000))
  }
}, 1000)

這樣無論頁面切到后臺多久,回來后都會 基于真實時間 計算,避免跳秒問題。

3. 高頻定時任務(wù) → 用 Web Worker

如果你有一些對精度要求很高的定時任務(wù)(比如心跳包、數(shù)據(jù)同步),而且不想被主線程阻塞,可以放到 Web Worker 里。

// worker.js
setInterval(() => {
  postMessage('ping')
}, 1000)

// main.js
const worker = new Worker('worker.js')
worker.onmessage = (e) => console.log(e.data)

因為 Worker 跑在獨立線程里,不受主線程卡頓影響,定時任務(wù)更穩(wěn)定。

4. 清理與管理機制

最后,不管用哪種方案,清理定時器 都是必做項。

Vue/React 組件卸載時,記得 clearInterval / cancelAnimationFrame,在頁面跳轉(zhuǎn)或模塊切換時,及時銷毀。

否則再好的方案,最后都有可能會出現(xiàn) 內(nèi)存泄漏 或者 其他的奇怪問題。

責任編輯:武曉燕 來源: 程序員Sunday
相關(guān)推薦

2022-09-13 17:54:55

CSS定時器監(jiān)聽事件

2024-04-11 09:17:51

ArraysJava安全

2022-05-06 16:12:40

定時器CSS前端

2017-01-12 19:59:25

Android注解詳解枚舉

2010-07-28 15:56:22

FlexTimer定時

2009-11-11 10:14:10

linux定時器操作系統(tǒng)

2025-08-06 10:00:00

瀏覽器slice()開發(fā)

2025-06-09 07:10:00

JavaScriptAPI開發(fā)

2024-10-11 16:34:22

2023-01-10 13:53:21

Linux定時器

2022-11-02 11:40:16

Flowable定時器流程

2012-07-19 10:03:32

2025-10-28 01:45:00

setTimeouAPI日志

2013-07-29 10:10:40

TCP協(xié)議TCP定時器TCP

2009-04-12 08:51:50

Symbian諾基亞移動OS

2011-02-23 10:20:45

2021-03-31 08:33:17

SysTick定時器SysTick定時器

2023-08-02 09:26:03

軟件定時器鴻蒙

2009-06-18 11:07:17

Spring fram

2017-03-06 14:08:38

JavaScript單線程setTimeout
點贊
收藏

51CTO技術(shù)棧公眾號