mirror of
https://github.com/samber/lo.git
synced 2025-09-26 20:11:13 +08:00
feat(debounce): add doc + accept multiple callback functions
This commit is contained in:
28
README.md
28
README.md
@@ -796,26 +796,24 @@ iter, err := lo.Attempt(0, func(i int) error {
|
||||
// nil
|
||||
```
|
||||
|
||||
For more advanced retry strategies (delay, exponential backoff...), please take a look on [cenkalti/backoff](https://github.com/cenkalti/backoff).
|
||||
|
||||
### Debounce
|
||||
creates a debounced instance that delays invoking func given until after wait milliseconds have elapsed.
|
||||
|
||||
`NewDebounce` creates a debounced instance that delays invoking functions given until after wait milliseconds have elapsed, until `cancel` is called.
|
||||
|
||||
```go
|
||||
f := func() {
|
||||
println("1. Called once after 100ms when func stopped invoking!")
|
||||
println("Called once after 100ms when debounce stopped invoking!")
|
||||
}
|
||||
d, cancel := lo.NewDebounce(100 * time.Millisecond, f)
|
||||
// f is invoked only 3 times
|
||||
for i := 0; i < 3; i++ {
|
||||
// No matter how many times you call it, it will be invoked only the last time after 100ms
|
||||
for j := 0; j < 10; j++ {
|
||||
d()
|
||||
}
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
|
||||
debounce, cancel := lo.NewDebounce(100 * time.Millisecond, f)
|
||||
for j := 0; j < 10; j++ {
|
||||
debounce()
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
cancel()
|
||||
// f will never be invoked again
|
||||
for i := 0; i < 3; i++ {
|
||||
d()
|
||||
}
|
||||
```
|
||||
|
||||
### Range / RangeFrom / RangeWithSteps
|
||||
@@ -846,8 +844,6 @@ result := Range(0);
|
||||
// []
|
||||
```
|
||||
|
||||
For more advanced retry strategies (delay, exponential backoff...), please take a look on [cenkalti/backoff](https://github.com/cenkalti/backoff).
|
||||
|
||||
## 🛩 Benchmark
|
||||
|
||||
We executed a simple benchmark with the a dead-simple `lo.Map` loop:
|
||||
|
52
retry.go
52
retry.go
@@ -5,36 +5,61 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Debounce struct {
|
||||
after time.Duration
|
||||
mu *sync.Mutex
|
||||
timer *time.Timer
|
||||
done bool
|
||||
type debounce struct {
|
||||
after time.Duration
|
||||
mu *sync.Mutex
|
||||
timer *time.Timer
|
||||
done bool
|
||||
callbacks []func()
|
||||
}
|
||||
|
||||
func (d *Debounce) add(f func()) *Debounce {
|
||||
func (d *debounce) reset() *debounce {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
if d.done {
|
||||
return d
|
||||
}
|
||||
|
||||
if d.timer != nil {
|
||||
d.timer.Stop()
|
||||
}
|
||||
d.timer = time.AfterFunc(d.after, f)
|
||||
|
||||
d.timer = time.AfterFunc(d.after, func() {
|
||||
for _, f := range d.callbacks {
|
||||
f()
|
||||
}
|
||||
})
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Debounce) cancel() {
|
||||
func (d *debounce) cancel() {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
if d.timer != nil {
|
||||
d.timer.Stop()
|
||||
d.timer = nil
|
||||
}
|
||||
|
||||
d.done = true
|
||||
}
|
||||
|
||||
// NewDebounce creates a debounced instance that delays invoking functions given until after wait milliseconds have elapsed.
|
||||
func NewDebounce(duration time.Duration, f ...func()) (func(), func()) {
|
||||
d := &debounce{
|
||||
after: duration,
|
||||
mu: new(sync.Mutex),
|
||||
timer: nil,
|
||||
done: false,
|
||||
callbacks: f,
|
||||
}
|
||||
|
||||
return func() {
|
||||
d.reset()
|
||||
}, d.cancel
|
||||
}
|
||||
|
||||
// Attempt invokes a function N times until it returns valid output. Returning either the caught error or nil. When first argument is less than `1`, the function runs until a sucessfull response is returned.
|
||||
func Attempt(maxIteration int, f func(int) error) (int, error) {
|
||||
var err error
|
||||
@@ -51,14 +76,3 @@ func Attempt(maxIteration int, f func(int) error) (int, error) {
|
||||
}
|
||||
|
||||
// throttle ?
|
||||
|
||||
// NewDebounce creates a debounced instance that delays invoking func given until after wait milliseconds have elapsed.
|
||||
func NewDebounce(duration time.Duration, f func()) (func(), func()) {
|
||||
d := &Debounce{
|
||||
mu: new(sync.Mutex),
|
||||
after: duration,
|
||||
}
|
||||
return func() {
|
||||
d.add(f)
|
||||
}, d.cancel
|
||||
}
|
||||
|
Reference in New Issue
Block a user