throttle
創建一個節流函數,限制函數的執行頻率。
基礎用法
typescript
import { throttle } from 'radash'
const throttledScroll = throttle(() => {
console.log('Scroll event handled')
}, 100)
window.addEventListener('scroll', throttledScroll)
// 滾動時,函數最多每100ms執行一次
語法
typescript
function throttle<T extends (...args: any[]) => any>(
fn: T,
delay: number,
options?: {
leading?: boolean
trailing?: boolean
}
): (...args: Parameters<T>) => void
參數
fn
(function): 要節流的函數delay
(number): 延遲時間(毫秒)options
(object, 可選): 配置選項leading
(boolean, 可選): 是否在開始時執行,默認為truetrailing
(boolean, 可選): 是否在結束時執行,默認為true
返回值
返回一個節流後的函數。
示例
基本節流
typescript
import { throttle } from 'radash'
const throttledLog = throttle((message: string) => {
console.log('Throttled:', message)
}, 1000)
// 快速連續調用
throttledLog('hello')
throttledLog('world')
throttledLog('example')
// 只有第一次調用會立即執行,後續調用會被節流
滾動事件節流
typescript
import { throttle } from 'radash'
const throttledScroll = throttle(() => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop
console.log('Scroll position:', scrollTop)
// 更新滾動指示器
updateScrollIndicator(scrollTop)
}, 100)
window.addEventListener('scroll', throttledScroll)
function updateScrollIndicator(scrollTop: number) {
const indicator = document.getElementById('scroll-indicator')
if (indicator) {
const percentage = (scrollTop / (document.body.scrollHeight - window.innerHeight)) * 100
indicator.style.width = `${percentage}%`
}
}
窗口大小調整節流
typescript
import { throttle } from 'radash'
const throttledResize = throttle(() => {
console.log('Window resized to:', window.innerWidth, 'x', window.innerHeight)
// 重新計算布局
recalculateLayout()
}, 250)
window.addEventListener('resize', throttledResize)
function recalculateLayout() {
// 重新計算頁面布局
console.log('Layout recalculated')
}
鼠標移動節流
typescript
import { throttle } from 'radash'
const throttledMouseMove = throttle((x: number, y: number) => {
console.log('Mouse position:', x, y)
// 更新鼠標位置顯示
updateMousePosition(x, y)
}, 50)
document.addEventListener('mousemove', (e) => {
throttledMouseMove(e.clientX, e.clientY)
})
function updateMousePosition(x: number, y: number) {
const positionElement = document.getElementById('mouse-position')
if (positionElement) {
positionElement.textContent = `X: ${x}, Y: ${y}`
}
}
鍵盤事件節流
typescript
import { throttle } from 'radash'
const throttledKeyPress = throttle((key: string) => {
console.log('Key pressed:', key)
// 處理鍵盤輸入
processKeyInput(key)
}, 200)
document.addEventListener('keydown', (e) => {
throttledKeyPress(e.key)
})
function processKeyInput(key: string) {
// 處理鍵盤輸入邏輯
console.log('Processing key:', key)
}
搜索輸入節流
typescript
import { throttle } from 'radash'
const searchInput = document.getElementById('search') as HTMLInputElement
const throttledSearch = throttle(async (query: string) => {
if (query.length < 2) return
const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`)
const results = await response.json()
displayResults(results)
}, 300)
searchInput.addEventListener('input', (e) => {
const query = (e.target as HTMLInputElement).value
throttledSearch(query)
})
function displayResults(results: any[]) {
console.log('Search results:', results)
}
只執行開始時的節流
typescript
import { throttle } from 'radash'
const leadingThrottle = throttle((action: string) => {
console.log('Action:', action)
}, 1000, { leading: true, trailing: false })
// 第一次調用立即執行
leadingThrottle('start')
leadingThrottle('middle')
leadingThrottle('end')
// 只有第一次調用會執行,後續調用被忽略
只執行結束時的節流
typescript
import { throttle } from 'radash'
const trailingThrottle = throttle((action: string) => {
console.log('Action:', action)
}, 1000, { leading: false, trailing: true })
// 第一次調用不會立即執行
trailingThrottle('start')
trailingThrottle('middle')
trailingThrottle('end')
// 只有最後一次調用會在延遲後執行
API調用節流
typescript
import { throttle } from 'radash'
const throttledApiCall = throttle(async (params: any) => {
const response = await fetch('/api/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params)
})
return response.json()
}, 500)
// 在用戶操作時調用
async function handleUserAction() {
const params = { action: 'update', data: { /* ... */ } }
const result = await throttledApiCall(params)
console.log('API result:', result)
}
復雜參數節流
typescript
import { throttle } from 'radash'
interface SearchParams {
query: string
filters: Record<string, any>
page: number
}
const throttledSearch = throttle(async (params: SearchParams) => {
const queryString = new URLSearchParams({
q: params.query,
page: params.page.toString(),
...params.filters
}).toString()
const response = await fetch(`/api/search?${queryString}`)
const results = await response.json()
return {
results,
total: results.length,
page: params.page
}
}, 500)
// 使用節流搜索
async function performSearch() {
const params: SearchParams = {
query: 'javascript',
filters: { category: 'programming', sort: 'relevance' },
page: 1
}
const result = await throttledSearch(params)
console.log('Search result:', result)
}
表單驗證節流
typescript
import { throttle } from 'radash'
const emailInput = document.getElementById('email') as HTMLInputElement
const throttledValidation = throttle(async (email: string) => {
if (!email.includes('@')) return
const response = await fetch('/api/validate-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email })
})
const result = await response.json()
if (result.valid) {
emailInput.classList.remove('error')
emailInput.classList.add('valid')
} else {
emailInput.classList.remove('valid')
emailInput.classList.add('error')
}
}, 300)
emailInput.addEventListener('input', (e) => {
const email = (e.target as HTMLInputElement).value
throttledValidation(email)
})
多個節流函數
typescript
import { throttle } from 'radash'
// 創建多個不同延遲的節流函數
const quickThrottle = throttle((action: string) => {
console.log('Quick action:', action)
}, 100)
const mediumThrottle = throttle((action: string) => {
console.log('Medium action:', action)
}, 500)
const slowThrottle = throttle((action: string) => {
console.log('Slow action:', action)
}, 1000)
// 使用不同的節流函數
quickThrottle('fast')
mediumThrottle('normal')
slowThrottle('slow')
條件節流
typescript
import { throttle } from 'radash'
const conditionalThrottle = throttle((value: string, shouldExecute: boolean) => {
if (shouldExecute) {
console.log('Executing with value:', value)
// 執行實際邏輯
processValue(value)
}
}, 300)
function processValue(value: string) {
// 處理值的邏輯
console.log('Processing:', value)
}
// 根據條件決定是否執行
conditionalThrottle('test', true)
conditionalThrottle('skip', false)
conditionalThrottle('execute', true)
性能監控節流
typescript
import { throttle } from 'radash'
const throttledPerformanceLog = throttle(() => {
const memory = performance.memory
console.log('Memory usage:', {
used: Math.round(memory.usedJSHeapSize / 1024 / 1024) + 'MB',
total: Math.round(memory.totalJSHeapSize / 1024 / 1024) + 'MB',
limit: Math.round(memory.jsHeapSizeLimit / 1024 / 1024) + 'MB'
})
}, 5000) // 每5秒最多執行一次
// 定期監控性能
setInterval(throttledPerformanceLog, 1000)
注意事項
- 延遲時間: 選擇合適的延遲時間,太短可能無效,太長影響響應性
- 內存洩漏: 節流函數會保持對原函數的引用
- leading/trailing: 控制函數在開始和結束時是否執行
- 異步函數: 節流函數可以包裝異步函數
- 參數傳遞: 節流函數會傳遞所有參數給原函數
與其他方法的區別
debounce()
: 延遲執行直到停止調用,節流是限制執行頻率throttle()
: 限制執行頻率,確保函數按固定間隔執行- 手動實現: 需要更多代碼和錯誤處理
實際應用場景
- 滾動事件: 優化滾動處理性能
- 窗口調整: 限制布局重新計算頻率
- 鼠標移動: 減少鼠標事件處理頻率
- 鍵盤事件: 限制鍵盤事件處理
- API調用: 防止頻繁的API請求