Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 32 additions & 32 deletions v2/debounce.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,29 +56,29 @@ func Chan[T any](in <-chan T, opts ...Option) <-chan T {
defer close(out)

var (
timer *time.Timer // Timer to manage delay
lastValue T // Last received value
hasValue bool // Whether a value is currently pending emission
count int // Number of delay resets since last emission
delayTimer *time.Timer // Timer to manage delay
lastValue T // Last received value
hasValue bool // Whether a value is currently pending emission
count int // Number of delay resets since last emission
)

// Function to return the timer channel or nil if timer is not set
// This avoids blocking on the timer channel if no timer is set
timerOrNil := func() <-chan time.Time {
if timer != nil {
return timer.C
emitLastValue := func() {
if hasValue {
out <- lastValue
hasValue = false
count = 0
if delayTimer != nil {
delayTimer.Stop()
}
}
return nil
}

for {
select {
case v, ok := <-in:
if !ok {
// Input channel closed — emit any pending value.
if hasValue {
out <- lastValue
}
emitLastValue()
return
}

Expand All @@ -90,30 +90,30 @@ func Chan[T any](in <-chan T, opts ...Option) <-chan T {

// Force emit if limit reached
if options.limit != 0 && count >= options.limit {
out <- v
hasValue = false
count = 0
if timer != nil {
timer.Stop()
}
emitLastValue()
continue
}

// Start or reset the delay timer
if timer == nil {
timer = time.NewTimer(options.delay)
} else {
timer.Reset(options.delay)
}
case <-timerOrNil():
// Delay has passed — emit the last value
if hasValue {
out <- lastValue
hasValue = false
count = 0
}
delayTimer = restartTimer(delayTimer, options.delay)
case <-timerChanOrNil(delayTimer):
emitLastValue()
}
}
}()
return out
}

func timerChanOrNil(timer *time.Timer) <-chan time.Time {
if timer != nil {
return timer.C
}
return nil
}

func restartTimer(timer *time.Timer, d time.Duration) *time.Timer {
if timer != nil {
timer.Reset(d)
return timer
}
return time.NewTimer(d)
}
Loading