# debounce-promise

Debounce an async function so a burst of calls collapses into one run.

Calls made inside a sliding `wait` window share a single run of the wrapped
function. Each call returns a future. Every future in the same window resolves to
the result of that one shared run. The window is trailing edge by default, so the
function runs `wait` after the last call in a burst.

## Installation

```toml
[dependencies]
debounce-promise = "0.1"
```

Run inside a Tokio runtime. Timers use `tokio::time`.

## Usage

```rust
use debounce_promise::Debounce;

# async fn run() {
let save = Debounce::latest(|value: &'static str| async move { Ok::<_, ()>(value) })
    .wait_ms(100)
    .build();

let a = save.call("foo");
let b = save.call("bar");
let c = save.call("qux");

// One run with the last argument. All three share its result.
assert_eq!((a.await, b.await, c.await), (Ok("qux"), Ok("qux"), Ok("qux")));
# }
```

### Leading edge

Set `leading(true)` to run the function at once on the first call of a fresh
window and return that result directly. Later calls in the same window join the
trailing run. A burst of N calls runs the function up to twice.

```rust
use debounce_promise::Debounce;

# async fn run() {
let save = Debounce::latest(|value: &'static str| async move { Ok::<_, ()>(value) })
    .wait_ms(100)
    .leading(true)
    .build();

let a = save.call("foo"); // leading, returns "foo"
let b = save.call("bar"); // joins trailing
let c = save.call("qux"); // joins trailing, last argument wins

assert_eq!((a.await, b.await, c.await), (Ok("foo"), Ok("qux"), Ok("qux")));
# }
```

### Accumulate

Use `Debounce::accumulate` to run the function once with the list of every
argument collected during the window. The caller at position `i` in the batch
receives `result[i]`.

```rust
use debounce_promise::Debounce;

# async fn run() {
let square = Debounce::accumulate(|batch: Vec<i32>| async move {
    Ok::<_, ()>(batch.iter().map(|x| x * x).collect::<Vec<_>>())
})
.wait_ms(100)
.build();

let one = square.call(1);
let two = square.call(2);
let three = square.call(3);

// One run with [1, 2, 3]. Each caller reads its own square.
assert_eq!((one.await, two.await, three.await), (Ok(1), Ok(4), Ok(9)));
# }
```

### Dynamic wait

`wait_fn` reads the window length from a closure on every call, so the wait can
change at runtime.

```rust
use std::time::Duration;
use debounce_promise::Debounce;

# fn build() {
let _d = Debounce::latest(|v: i32| async move { Ok::<_, ()>(v) })
    .wait_fn(|| Duration::from_millis(50))
    .build();
# }
```

## Errors

The wrapped function returns `Result`. If it returns `Err`, every caller in that
window receives a clone of the same error. The result and error types must be
`Clone`.

## License

Licensed under the [MIT license](LICENSE).
