debounce

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 18, 2023 License: MIT Imports: 2 Imported by: 0

README

debounce

Go package that provides a number of debounce patterns as a set of easy to use functions.

Go Reference GitHub tag (latest SemVer) Actions Status Coverage GitHub issues GitHub pull requests License Status

Provides functions to debounce function calls, i.e., to ensure that a function is only executed after a certain amount of time has passed since the last call.

Debouncing can be useful in scenarios where function calls may be triggered rapidly, such as in response to user input, but the underlying operation is expensive and only needs to be performed once per batch of calls.

This package provides several debouncing functions, each with different characteristics:

  • New: creates a new debounced function that will wait a fixed duration before calling the original function, regardless of how many times the debounced function is called in the meantime.
  • NewMutable: creates a new debounced function that will wait a fixed duration before calling the last function that was passed to the debounced function, regardless of how many times the debounced function is called in the meantime. This allows the function to be changed dynamically.
  • NewWithMaxWait: creates a new debounced function that will wait a fixed duration before calling the original function, but will also enforce a maximum wait time, after which the function will be called regardless of whether new calls have been made. This ensures that the function is not delayed indefinitely if calls keep coming in.
  • NewMutableWithMaxWait: creates a new debounced function that combines the characteristics of NewMutable and NewWithMaxWait, i.e., it will wait a fixed duration before calling the last function that was passed to the debounced function, but will also enforce a maximum wait time. All debouncing functions are safe for concurrent use in goroutines and can be called multiple times.

Import

import "github.com/romdo/go-debounce"

Usage

func main() {
	// Create a new debouncer that will wait 100 milliseconds since the last
	// call before calling the callback function.
	debounced, _ := debounce.New(100*time.Millisecond, func() {
		fmt.Println("Hello, world!")
	})

	debounced()
	time.Sleep(75 * time.Millisecond) // +75ms = 75ms
	debounced()
	time.Sleep(75 * time.Millisecond) // +75ms = 150ms
	debounced()
	time.Sleep(150 * time.Millisecond) // +150ms = 300ms, wait expired at 250ms

	// Output:
	// Hello, world!
}

Documentation

Please see the Go Reference.

Contributing

Contributions to this package are welcome! Please open an issue or a pull request on GitHub.

License

MIT

Documentation

Overview

Package debounce provides functions to debounce function calls, i.e., to ensure that a function is only executed after a certain amount of time has passed since the last call.

Debouncing can be useful in scenarios where function calls may be triggered rapidly, such as in response to user input, but the underlying operation is expensive and only needs to be performed once per batch of calls.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(wait time.Duration, f func()) (debounced func(), cancel func())

New returns a debounced function that delays invoking f until after wait time has elapsed since the last time the debounced function was invoked.

The returned cancel function can be used to cancel any pending invocation of f, but is not required to be called, so can be ignored if not needed.

Both debounced and cancel functions are safe for concurrent use in goroutines, and can both be called multiple times.

The debounced function does not wait for f to complete, so f needs to be thread-safe as it may be invoked again before the previous invocation completes.

Example
// Create a new debouncer that will wait 100 milliseconds since the last
// call before calling the callback function.
debounced, _ := debounce.New(100*time.Millisecond, func() {
	fmt.Println("Hello, world!")
})

debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 75ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 150ms
debounced()
time.Sleep(150 * time.Millisecond) // +150ms = 300ms, wait expired at 250ms

debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 675ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 750ms
debounced()
time.Sleep(150 * time.Millisecond) // +150ms = 900ms, wait expired at 850ms
Output:

Hello, world!
Hello, world!
Example (With_cancel)
// Create a new debouncer that will wait 100 milliseconds since the last
// call before calling the callback function.
debounced, cancel := debounce.New(100*time.Millisecond, func() {
	fmt.Println("Hello, world!")
})

debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 75ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 150ms
debounced()
time.Sleep(150 * time.Millisecond) // +150ms = 300ms, wait expired at 250ms

debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 375ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 450ms
cancel()
time.Sleep(150 * time.Millisecond) // +150ms = 600ms, canceled at 450ms

debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 675ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 750ms
debounced()
time.Sleep(150 * time.Millisecond) // +150ms = 900ms, wait expired at 850ms
Output:

Hello, world!
Hello, world!

func NewMutable

func NewMutable(wait time.Duration) (debounced func(f func()), cancel func())

NewMutable returns a debounced function like New, but it allows callback function f to be changed, as a new callback function is passed to each invocation of the debounced function.

The returned cancel function can be used to cancel any pending invocation of f, but is not required to be called, so can be ignored if not needed.

Only the very last f passed to the debounced function is called when the delay expires and the callback function is invoked. Previous f values are discarded.

Both debounced and cancel functions are safe for concurrent use in goroutines, and can both be called multiple times.

Example
// Create a new debouncer that will wait 100 milliseconds before calling
// given callback functions.
debounced, _ := debounce.NewMutable(100 * time.Millisecond)

debounced(func() { fmt.Println("Hello, world! #1") })
time.Sleep(75 * time.Millisecond) // +75ms = 75ms
debounced(func() { fmt.Println("Hello, world! #2") })
time.Sleep(75 * time.Millisecond) // +75ms = 150ms
debounced(func() { fmt.Println("Hello, world! #3") })
time.Sleep(150 * time.Millisecond) // +150ms = 300ms, wait expired at 250ms

debounced(func() { fmt.Println("Hello, world! #4") })
time.Sleep(75 * time.Millisecond) // +75ms = 375ms
debounced(func() { fmt.Println("Hello, world! #5") })
time.Sleep(75 * time.Millisecond) // +75ms = 450ms
debounced(func() { fmt.Println("Hello, world! #6") })
time.Sleep(150 * time.Millisecond) // +150ms = 600ms, wait expired at 550ms
Output:

Hello, world! #3
Hello, world! #6
Example (With_cancel)
// Create a new debouncer that will wait 100 milliseconds before calling
// given callback functions.
debounced, cancel := debounce.NewMutable(100 * time.Millisecond)

debounced(func() { fmt.Println("Hello, world! #1") })
time.Sleep(75 * time.Millisecond) // +75ms = 75ms
debounced(func() { fmt.Println("Hello, world! #2") })
time.Sleep(75 * time.Millisecond) // +75ms = 150ms
debounced(func() { fmt.Println("Hello, world! #3") })
time.Sleep(150 * time.Millisecond) // +150ms = 300ms, wait expired at 250ms

debounced(func() { fmt.Println("Hello, world! #4") })
time.Sleep(75 * time.Millisecond) // +75ms = 375ms
debounced(func() { fmt.Println("Hello, world! #5") })
time.Sleep(75 * time.Millisecond) // +75ms = 450ms
cancel()
time.Sleep(150 * time.Millisecond) // +150ms = 600ms, canceled at 450ms

debounced(func() { fmt.Println("Hello, world! #6") })
time.Sleep(75 * time.Millisecond) // +75ms = 675ms
debounced(func() { fmt.Println("Hello, world! #7") })
time.Sleep(75 * time.Millisecond) // +75ms = 750ms
debounced(func() { fmt.Println("Hello, world! #8") })
time.Sleep(150 * time.Millisecond) // +150ms = 900ms, wait expired at 850ms
Output:

Hello, world! #3
Hello, world! #8

func NewMutableWithMaxWait

func NewMutableWithMaxWait(
	wait, maxWait time.Duration,
) (debounced func(f func()), cancel func())

NewMutableWithMaxWait is a combination of NewMutable and NewWithMaxWait.

When either of the wait or maxWait timers expire, the last f passed to the debounced function is called.

The returned cancel function can be used to cancel any pending invocation of f, but is not required to be called, so can be ignored if not needed.

Both debounced and cancel functions are safe for concurrent use in goroutines, and can both be called multiple times.

Example
// Create a new debouncer that will wait 100 milliseconds before calling
// given callback functions, on repeated debounce calls, it will wait no
// more than 500 milliseconds before calling the callback function.
debounced, _ := debounce.NewMutableWithMaxWait(
	100*time.Millisecond, 500*time.Millisecond,
)

debounced(func() { fmt.Println("Hello, world! #1") })
time.Sleep(75 * time.Millisecond) // +75ms = 75ms
debounced(func() { fmt.Println("Hello, world! #2") })
time.Sleep(75 * time.Millisecond) // +75ms = 150ms
debounced(func() { fmt.Println("Hello, world! #3") })
time.Sleep(75 * time.Millisecond) // +75ms = 225ms
debounced(func() { fmt.Println("Hello, world! #4") })
time.Sleep(75 * time.Millisecond) // +75ms = 300ms
debounced(func() { fmt.Println("Hello, world! #5") })
time.Sleep(75 * time.Millisecond) // +75ms = 375ms
debounced(func() { fmt.Println("Hello, world! #6") })
time.Sleep(75 * time.Millisecond) // +75ms = 450ms
debounced(func() { fmt.Println("Hello, world! #7") })
time.Sleep(75 * time.Millisecond) // +75ms = 525ms, maxWait expired at 500ms
debounced(func() { fmt.Println("Hello, world! #8") })
time.Sleep(75 * time.Millisecond) // +75ms = 600ms
debounced(func() { fmt.Println("Hello, world! #9") })
time.Sleep(150 * time.Millisecond) // +150ms = 750ms, wait expired at 700ms
Output:

Hello, world! #7
Hello, world! #9
Example (With_cancel)
// Create a new debouncer that will wait 100 milliseconds before calling
// given callback functions, on repeated debounce calls, it will wait no
// more than 500 milliseconds before calling the callback function.
debounced, cancel := debounce.NewMutableWithMaxWait(
	100*time.Millisecond, 500*time.Millisecond,
)

debounced(func() { fmt.Println("Hello, world! #1") })
time.Sleep(75 * time.Millisecond) // +75ms = 75ms
debounced(func() { fmt.Println("Hello, world! #2") })
time.Sleep(75 * time.Millisecond) // +75ms = 150ms
debounced(func() { fmt.Println("Hello, world! #3") })
time.Sleep(75 * time.Millisecond) // +75ms = 225ms
debounced(func() { fmt.Println("Hello, world! #4") })
time.Sleep(75 * time.Millisecond) // +75ms = 300ms
debounced(func() { fmt.Println("Hello, world! #5") })
time.Sleep(75 * time.Millisecond) // +75ms = 375ms
debounced(func() { fmt.Println("Hello, world! #6") })
time.Sleep(75 * time.Millisecond) // +75ms = 450ms
cancel()
time.Sleep(75 * time.Millisecond) // +150 = 525ms, canceled at 450ms
debounced(func() { fmt.Println("Hello, world! #8") })
time.Sleep(75 * time.Millisecond) // +75ms = 600ms
debounced(func() { fmt.Println("Hello, world! #9") })
time.Sleep(150 * time.Millisecond) // +150ms = 750ms, wait expired at 700ms
Output:

Hello, world! #9

func NewWithMaxWait

func NewWithMaxWait(
	wait, maxWait time.Duration,
	f func(),
) (debounced func(), cancel func())

NewWithMaxWait returns a debounced function like New, but with a maximum wait time of maxWait, which is the maximum time f is allowed to be delayed before it is invoked.

The returned cancel function can be used to cancel any pending invocation of f, but is not required to be called, so can be ignored if not needed.

Both debounced and cancel functions are safe for concurrent use in goroutines, and can both be called multiple times.

The debounced function does not wait for f to complete, so f needs to be thread-safe as it may be invoked again before the previous invocation completes.

Example
// Create a new debouncer that will wait 100 milliseconds since the last
// call before calling the callback function. On repeated calls, it will
// wait no more than 500 milliseconds before calling the callback function.
debounced, _ := debounce.NewWithMaxWait(
	100*time.Millisecond, 500*time.Millisecond,
	func() { fmt.Println("Hello, world!") },
)

debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 75ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 150ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 225ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 300ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 375ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 450ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 525ms, maxWait expired at 500ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 600ms
debounced()
time.Sleep(150 * time.Millisecond) // +150ms = 750ms, wait expired at 700ms
Output:

Hello, world!
Hello, world!
Example (With_cancel)
// Create a new debouncer that will wait 100 milliseconds since the last
// call before calling the callback function. On repeated calls, it will
// wait no more than 500 milliseconds before calling the callback function.
debounced, cancel := debounce.NewWithMaxWait(
	100*time.Millisecond, 500*time.Millisecond,
	func() { fmt.Println("Hello, world!") },
)

debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 75ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 150ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 225ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 300ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 375ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 450ms
cancel()
time.Sleep(150 * time.Millisecond) // +150ms = 600ms, canceled at 450ms
debounced()
time.Sleep(75 * time.Millisecond) // +75ms = 675ms
debounced()
time.Sleep(150 * time.Millisecond) // +150ms = 825ms, wait expired at 775ms
Output:

Hello, world!

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL