beek
beek

Reputation: 3750

Debounce in Redux Saga

I found this useful little function to throttle based on which key is saving in Redux Saga

export default function* throttlePerKey(pattern:string, selector: Function, timeout:number, saga:any) {
    const set = new Set()
  
    while(true) {
      const action = yield take(pattern)
      const id = selector(action)
      const throttled = set.has(id)
     
      if (throttled) {
         
      } else {
        set.add(id)
        // Expire items after timeout
        yield fork(function* () {
          yield delay(timeout)
          set.delete(id)
        })
        yield call(saga, action)
      }
    }
  }

I'm trying now to make it debounce instead. So you always get the last one.

Any clues how to do that?

Upvotes: 0

Views: 1105

Answers (1)

Nicholas Tower
Nicholas Tower

Reputation: 84912

When the action happens for the first time, you can fork a task that sets a delay followed by a call to the saga, and save the task object. If the action happens a second time soon after, you'll cancel the task and start another one. Once enough time passes without any actions, the last task will make it past its delay, and call the saga.

export default function* debouncePerKey(pattern:string, selector: Function, timeout:number, saga:any) {
  const map = new Map()

  while(true) {
    const action = yield take(pattern)
    const id = selector(action)
    const existingTask = map.get(id)

    if (existingTask) {
      yield cancel(existingTask)
    }
   
    const newTask = yield fork(function* () {
      yield delay(timeout)
      map.delete(id)
      yield call(saga, action)
    })

    map.set(id, newTask)
  }
}

Upvotes: 2

Related Questions