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请求