Skip to content

Commit

Permalink
fix singular throttle event dispatched two times
Browse files Browse the repository at this point in the history
Relates to: phoenixframework#3097

So, in phoenixframework#3097 I changed the throttle behavior to also dispatch an event
after the throttle time has passed to make sure that the last event is
dispatched. However, this caused the event to be dispatched twice in the
case that there was only one event in the first place.

This fixes that, although the throttle code is still a bit of a mess and
should probably be refactored completely at some point.
  • Loading branch information
SteffenDE committed Feb 9, 2024
1 parent e07a58e commit 767b40e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 deletions.
19 changes: 12 additions & 7 deletions assets/js/phoenix_live_view/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,21 +222,25 @@ let DOM = {
default:
let timeout = parseInt(value)
let trigger = (blur) => {
const throttled = this.private(el, THROTTLED)
if(blur){
// if the input is blurred, we need to cancel the next throttle timeout
// therefore we store the timer id in the THROTTLED private attribute
if(throttle && this.private(el, THROTTLED)){
clearTimeout(this.private(el, THROTTLED))
if(throttle && throttled !== null){
clearTimeout(throttled.timeout)
this.deletePrivate(el, THROTTLED)
}
// on debounce we just trigger the callback
return callback()
}
// no blur, remove the throttle attribute if we are in throttle mode
if(throttle) this.deletePrivate(el, THROTTLED)
// always call the callback to ensure that the latest event is processed,
// even when throttle is active
callback()
if(throttle){
this.deletePrivate(el, THROTTLED)
// run callback if there was a throttled event
if(throttled && throttled.updated) callback()
} else {
callback()
}
}
let currentCycle = this.incCycle(el, DEBOUNCE_TRIGGER, trigger)
if(isNaN(timeout)){ return logError(`invalid throttle/debounce value: ${value}`) }
Expand All @@ -249,6 +253,7 @@ let DOM = {
}

if(!newKeyDown && this.private(el, THROTTLED)){
this.updatePrivate(el, THROTTLED, {}, (existing) => ({...existing, updated: true}))
return false
} else {
callback()
Expand All @@ -259,7 +264,7 @@ let DOM = {
const t = setTimeout(() => {
if(asyncFilter()){ this.triggerCycle(el, DEBOUNCE_TRIGGER) }
}, timeout)
this.putPrivate(el, THROTTLED, t)
this.putPrivate(el, THROTTLED, {timer: t})
}
} else {
setTimeout(() => {
Expand Down
19 changes: 19 additions & 0 deletions assets/test/debounce_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,25 @@ describe("throttle", function (){
done()
})
})

test("triggers only once when there is only one event", done => {
let calls = 0
let el = container().querySelector("#throttle-200")

el.addEventListener("click", e => {
DOM.debounce(el, e, "phx-debounce", 100, "phx-throttle", 200, () => true, () => {
calls++
el.innerText = `now:${calls}`
})
})
DOM.dispatchEvent(el, "click")
expect(calls).toBe(1)
expect(el.innerText).toBe("now:1")
after(250, () => {
expect(calls).toBe(1)
done()
})
})
})


Expand Down

0 comments on commit 767b40e

Please sign in to comment.