Skip to content

Commit 8ba3b9d

Browse files
authored
fix(watchThrottled): duplicate callback invokation when leading and trailing edges coincide (#1593)
1 parent cd6f856 commit 8ba3b9d

File tree

3 files changed

+21
-25
lines changed

3 files changed

+21
-25
lines changed

packages/core/useThrottledRefHistory/index.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('useThrottledRefHistory - sync', () => {
1616

1717
await promiseTimeout(ms * 3)
1818

19-
expect(history.value.length).toBe(3)
19+
expect(history.value.length).toBe(2)
2020
expect(history.value[0].snapshot).toBe(100)
2121

2222
v.value = 200
@@ -25,7 +25,7 @@ describe('useThrottledRefHistory - sync', () => {
2525

2626
await promiseTimeout(ms * 3)
2727

28-
expect(history.value.length).toBe(5)
28+
expect(history.value.length).toBe(3)
2929
expect(history.value[0].snapshot).toBe(400)
3030
})
3131
})

packages/shared/utils/filters.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export function debounceFilter(ms: MaybeRef<number>, options: DebounceFilterOpti
103103
export function throttleFilter(ms: MaybeRef<number>, trailing = true, leading = true) {
104104
let lastExec = 0
105105
let timer: ReturnType<typeof setTimeout> | undefined
106-
let preventLeading = !leading
106+
let isLeading = true
107107

108108
const clear = () => {
109109
if (timer) {
@@ -123,24 +123,23 @@ export function throttleFilter(ms: MaybeRef<number>, trailing = true, leading =
123123
return invoke()
124124
}
125125

126-
if (elapsed > duration) {
126+
if (elapsed > duration && (leading || !isLeading)) {
127127
lastExec = Date.now()
128-
if (preventLeading)
129-
preventLeading = false
130-
else invoke()
128+
invoke()
131129
}
132-
if (trailing) {
130+
else if (trailing) {
133131
timer = setTimeout(() => {
134132
lastExec = Date.now()
135-
if (!leading)
136-
preventLeading = true
133+
isLeading = true
137134
clear()
138135
invoke()
139136
}, duration)
140137
}
141138

142139
if (!leading && !timer)
143-
timer = setTimeout(() => preventLeading = true, duration)
140+
timer = setTimeout(() => isLeading = true, duration)
141+
142+
isLeading = false
144143
}
145144

146145
return filter

packages/shared/utils/index.test.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,20 +77,6 @@ describe('filters', () => {
7777
expect(debouncedFilterSpy).toHaveBeenCalledTimes(2)
7878
})
7979

80-
it('should throttle', () => {
81-
const debouncedFilterSpy = vitest.fn()
82-
const filter = createFilterWrapper(throttleFilter(1000), debouncedFilterSpy)
83-
84-
setTimeout(filter, 500)
85-
setTimeout(filter, 500)
86-
setTimeout(filter, 500)
87-
setTimeout(filter, 500)
88-
89-
vitest.runAllTimers()
90-
91-
expect(debouncedFilterSpy).toHaveBeenCalledTimes(2)
92-
})
93-
9480
it('should throttle with ref', () => {
9581
const debouncedFilterSpy = vitest.fn()
9682
const throttle = ref(0)
@@ -107,4 +93,15 @@ describe('filters', () => {
10793

10894
expect(debouncedFilterSpy).toHaveBeenCalledTimes(2)
10995
})
96+
97+
it('should not duplicate single event', () => {
98+
const debouncedFilterSpy = vitest.fn()
99+
const filter = createFilterWrapper(throttleFilter(1000), debouncedFilterSpy)
100+
101+
setTimeout(filter, 500)
102+
103+
vitest.runAllTimers()
104+
105+
expect(debouncedFilterSpy).toHaveBeenCalledTimes(1)
106+
})
110107
})

0 commit comments

Comments
 (0)