別再瘋狂調用你的 API 了!學會防抖與節流
幾個月前,我在寫一個搜索框 —— 那種“邊輸入邊搜索”的實時提示功能。
一開始一切順利,直到我飛快打了幾個字,后臺日志就像加班焦慮的實習生一樣開始狂吼:
“5 秒內處理了 400 次請求。”
我愣住了。
隊友悠悠地來了一句:
“哥們,是時候冷靜一下了。”
那一刻我意識到:
是的,我聽說過“防抖”(debounce),也聽說過“節流”(throttle)。
但它們到底怎么用,什么時候用,我內心一直歸到那個抽屜——“以后有空一定搞懂。”
那么,現在就來真正搞懂它們
我終于把防抖與節流整明白了。
這篇文章不會跟你講一堆術語,而是從實際開發需求出發,告訴你它們的本質差異和應用場景。
防抖 vs 節流,到底有啥區別?
一句話總結:
- 防抖(debounce):等你停下來,我再執行
- 節流(throttle):規定時間內只能執行一次
聽起來像是兄弟倆,但性格完全不同。
Debounce:等等...再等等...
場景: 用戶在搜索框輸入內容,你希望只在他停下 300ms 后再發出請求。
function debounce(fn, delay) {
let timer
return (...args) => {
clearTimeout(timer)
timer = setTimeout(() => fn(...args), delay)
}
}
適合用在:
- 搜索框輸入(不打完不請求)
- 輸入自動保存(暫停一下才保存)
- 頁面 resize(用戶調整完再處理)
邏輯關鍵詞:每次觸發都會重置計時器,只有“沉默”一段時間后才執行。
Throttle:給我一點節奏感
場景: 用戶在瘋狂滾動頁面,你想追蹤他的行為,但沒必要每一像素都記錄一次。
function throttle(fn, limit) {
let lastTime = 0
return (...args) => {
const now = Date.now()
if (now - lastTime >= limit) {
lastTime = now
fn(...args)
}
}
}
適合用在:
- 頁面滾動事件
- 鼠標移動追蹤
- resize 實時反饋(希望“過程中”就執行)
邏輯關鍵詞:固定頻率執行,即使觸發頻率再高也“控頻”。
該選哪個?
目標 | 使用方式 |
用戶操作結束后再執行 | ? 使用防抖 debounce |
用戶操作過程中定時執行 | ? 使用節流 throttle |
真正的場景:不是 MDN 抄過來就完事了
你可能會遇到這樣的情況:
- 一個搜索建議接口,用戶打字太快,結果請求太多(→ 用防抖)
- 頁面滾動時觸發組件動畫或懶加載(→ 用節流)
- 表單自動保存草稿,用戶停頓 1 秒后提交(→ 用防抖)
- 追蹤用戶鼠標軌跡但別搞崩瀏覽器(→ 用節流)
BONUS:Lodash 了解一下
實話實說,大部分項目里你都有 lodash,那還費什么勁?
import { debounce, throttle } from 'lodash'
- 想防抖就
debounce(fn, 300)
- 想節流就
throttle(fn, 200)
別忘了在 React 組件里 清理定時器:
useEffect(() => {
const handler = debounce(() => { /* do something */ }, 300)
return () => handler.cancel()
}, [])
最后的建議:別讓你的函數失控!
很多開發者在加交互效果時,忽略了性能成本:
- 鍵盤事件、滾動事件、窗口變化,這些都可能每秒觸發上百次
- 忽視控制,輕則頁面卡頓,重則服務器被打爆
了解防抖與節流,拯救了我的 API 賬單、頁面性能和代碼審查時的自尊。
所以如果你以前也裝懂過“debounce vs throttle”,別擔心,我懂你。
現在開始,防抖請耐心,節流請克制。
別再讓函數亂跑,掌控它們,才是真正的前端高手。