Skip to content

throttle

Create a throttled function that limits the execution frequency of functions.

Basic Usage

typescript
import { throttle } from 'radash'

const throttledScroll = throttle(() => {
  console.log('Scroll event handled')
}, 100)

window.addEventListener('scroll', throttledScroll)

Syntax

typescript
function throttle<T extends (...args: any[]) => any>(
  fn: T,
  delay: number,
  options?: {
    leading?: boolean
    trailing?: boolean
  }
): T

Parameters

  • fn (function): The function to throttle
  • delay (number): The minimum time interval between function calls (in milliseconds)
  • options (object, optional): Throttle options
    • leading (boolean): Whether to execute on the leading edge (default: true)
    • trailing (boolean): Whether to execute on the trailing edge (default: true)

Return Value

Returns a throttled function with the same signature as the original function.

Examples

Basic Throttling

typescript
import { throttle } from 'radash'

const expensiveOperation = () => {
  console.log('Expensive operation executed')
}

const throttledOperation = throttle(expensiveOperation, 1000)

// Call multiple times rapidly
throttledOperation() // Executed immediately
throttledOperation() // Ignored
throttledOperation() // Ignored
// After 1 second, the next call will be executed

Scroll Event Throttling

typescript
import { throttle } from 'radash'

const handleScroll = () => {
  console.log('Scroll position:', window.scrollY)
}

const throttledScroll = throttle(handleScroll, 100)

window.addEventListener('scroll', throttledScroll)

API Call Throttling

typescript
import { throttle } from 'radash'

const fetchData = async (query: string) => {
  const response = await fetch(`https://api.example.com/search?q=${query}`)
  return response.json()
}

const throttledFetch = throttle(fetchData, 500)

// Search input handler
const handleSearch = async (query: string) => {
  try {
    const results = await throttledFetch(query)
    console.log('Search results:', results)
  } catch (error) {
    console.error('Search failed:', error)
  }
}

// Usage in search input
document.getElementById('search').addEventListener('input', (e) => {
  handleSearch(e.target.value)
})

Mouse Move Throttling

typescript
import { throttle } from 'radash'

const handleMouseMove = (event: MouseEvent) => {
  console.log('Mouse position:', event.clientX, event.clientY)
}

const throttledMouseMove = throttle(handleMouseMove, 50)

document.addEventListener('mousemove', throttledMouseMove)

Window Resize Throttling

typescript
import { throttle } from 'radash'

const handleResize = () => {
  console.log('Window size:', window.innerWidth, 'x', window.innerHeight)
}

const throttledResize = throttle(handleResize, 200)

window.addEventListener('resize', throttledResize)

Keyboard Event Throttling

typescript
import { throttle } from 'radash'

const handleKeyPress = (event: KeyboardEvent) => {
  console.log('Key pressed:', event.key)
}

const throttledKeyPress = throttle(handleKeyPress, 100)

document.addEventListener('keydown', throttledKeyPress)

Leading Edge Only

typescript
import { throttle } from 'radash'

const handleClick = () => {
  console.log('Button clicked')
}

const throttledClick = throttle(handleClick, 1000, { 
  leading: true, 
  trailing: false 
})

// Only executes on the first call within the throttle period
document.getElementById('button').addEventListener('click', throttledClick)

Trailing Edge Only

typescript
import { throttle } from 'radash'

const handleInput = (value: string) => {
  console.log('Input value:', value)
}

const throttledInput = throttle(handleInput, 300, { 
  leading: false, 
  trailing: true 
})

// Only executes on the last call within the throttle period
document.getElementById('input').addEventListener('input', (e) => {
  throttledInput(e.target.value)
})

Complex Parameter Throttling

typescript
import { throttle } from 'radash'

const processData = (data: any[], options: { filter?: boolean, sort?: boolean }) => {
  console.log('Processing data:', data.length, 'items')
  console.log('Options:', options)
}

const throttledProcess = throttle(processData, 500)

// Multiple calls with different parameters
throttledProcess([1, 2, 3], { filter: true })
throttledProcess([4, 5, 6], { sort: true })
throttledProcess([7, 8, 9], { filter: true, sort: true })

Cancel Throttled Function

typescript
import { throttle } from 'radash'

const expensiveOperation = () => {
  console.log('Expensive operation')
}

const throttledOperation = throttle(expensiveOperation, 1000)

// Start throttled operation
throttledOperation()

// Cancel the throttled function
if (throttledOperation.cancel) {
  throttledOperation.cancel()
  console.log('Throttled function cancelled')
}

Multiple Throttled Functions

typescript
import { throttle } from 'radash'

const logScroll = () => console.log('Scroll logged')
const logResize = () => console.log('Resize logged')
const logMouse = () => console.log('Mouse logged')

const throttledScroll = throttle(logScroll, 100)
const throttledResize = throttle(logResize, 200)
const throttledMouse = throttle(logMouse, 50)

// Add event listeners
window.addEventListener('scroll', throttledScroll)
window.addEventListener('resize', throttledResize)
document.addEventListener('mousemove', throttledMouse)

Conditional Throttling

typescript
import { throttle } from 'radash'

const handleEvent = (eventType: string, data: any) => {
  console.log(`${eventType} event:`, data)
}

const throttledHandler = throttle(handleEvent, 300)

// Conditional throttling based on event type
const handleConditionalEvent = (eventType: string, data: any) => {
  if (eventType === 'scroll' || eventType === 'resize') {
    throttledHandler(eventType, data)
  } else {
    handleEvent(eventType, data) // No throttling for other events
  }
}

window.addEventListener('scroll', () => handleConditionalEvent('scroll', { y: window.scrollY }))
window.addEventListener('resize', () => handleConditionalEvent('resize', { width: window.innerWidth }))
document.addEventListener('click', () => handleConditionalEvent('click', { timestamp: Date.now() }))

Performance Monitoring with Throttling

typescript
import { throttle } from 'radash'

const monitorPerformance = () => {
  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'
  })
}

const throttledMonitor = throttle(monitorPerformance, 5000) // Check every 5 seconds

// Monitor performance periodically
setInterval(throttledMonitor, 1000)

Form Validation Throttling

typescript
import { throttle } from 'radash'

const validateField = (fieldName: string, value: string) => {
  const errors = []
  
  if (fieldName === 'email' && !value.includes('@')) {
    errors.push('Invalid email format')
  }
  
  if (fieldName === 'password' && value.length < 8) {
    errors.push('Password must be at least 8 characters')
  }
  
  console.log(`${fieldName} validation:`, errors.length === 0 ? 'Valid' : errors)
  return errors
}

const throttledValidation = throttle(validateField, 300)

// Form field validation
document.getElementById('email').addEventListener('input', (e) => {
  throttledValidation('email', e.target.value)
})

document.getElementById('password').addEventListener('input', (e) => {
  throttledValidation('password', e.target.value)
})

API Rate Limiting

typescript
import { throttle } from 'radash'

const apiCall = async (endpoint: string, data: any) => {
  const response = await fetch(endpoint, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data)
  })
  return response.json()
}

const throttledApiCall = throttle(apiCall, 1000) // Max 1 call per second

// Usage
const sendData = async (data: any) => {
  try {
    const result = await throttledApiCall('/api/data', data)
    console.log('API response:', result)
  } catch (error) {
    console.error('API call failed:', error)
  }
}

// Multiple rapid calls
sendData({ id: 1, value: 'test' })
sendData({ id: 2, value: 'test2' })
sendData({ id: 3, value: 'test3' })
// Only the first call will be executed immediately, others will be throttled

Notes

  1. Execution control: Limits function execution frequency
  2. Performance: Reduces unnecessary function calls
  3. User experience: Prevents overwhelming the system
  4. Configurable: Supports leading and trailing edge execution
  5. Cancellable: Can cancel pending executions

Differences from Other Methods

  • throttle: Limits execution frequency to a maximum rate
  • debounce: Delays execution until calls stop
  • memo: Caches function results
  • throttle(): More predictable execution timing

Performance

  • Time Complexity: O(1) for throttle creation
  • Memory: Minimal overhead for function wrapping
  • Use Cases: Event handling, API rate limiting, performance optimization

Released under the MIT License.