Skip to content

Commit

Permalink
Support an options-object
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Nov 15, 2023
1 parent 1f6cd9b commit 60a50c4
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 4 deletions.
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The returned function has a `.clear()` method to cancel scheduled executions, an
declare function debounce<F extends AnyFunction>(
function_: F,
wait?: number,
immediate?: boolean
options?: {immediate: boolean}
): debounce.DebouncedFunction<F>;

declare namespace debounce {
Expand Down
9 changes: 8 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
function debounce(function_, wait = 100, immediate) {
function debounce(function_, wait = 100, options = {}) {
if (wait < 0) {
throw new RangeError('`wait` must not be negative.');
}

// TODO: Deprecate the boolean parameter at some point.
const {immediate} = typeof options === 'boolean' ? {immediate: options} : options;

let storedContext;
let storedArguments;
let timeoutId;
Expand Down
6 changes: 4 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ function resize() {
window.onresize = debounce(resize, 200);
```

*(You can also use `const debounce = require('debounce')`)*

To later clear the timer and cancel currently scheduled executions:

```js
Expand All @@ -35,11 +37,11 @@ window.onresize.flush();

## API

### debounce(fn, wait, immediate?)
### debounce(fn, wait, options?)

Creates a debounced function that delays execution until `wait` milliseconds have passed since its last invocation.

Set the `immediate` parameter to `true` to invoke the function immediately at the start of the `wait` interval, preventing issues such as double-clicks on a button.
Set the `immediate` option to `true` to invoke the function immediately at the start of the `wait` interval, preventing issues such as double-clicks on a button.

The returned function has a `.clear()` method to cancel scheduled executions, and a `.flush()` method for immediate execution and resetting the timer for future calls.

Expand Down
50 changes: 50 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,53 @@ test('context check in debounced function', async t => {
assert.ok(errorThrown, 'An error should have been thrown');
});
});

test('immediate execution', async t => {
let clock;

await t.test('should execute immediately when immediate is true', async () => {
clock = sinon.useFakeTimers();
const callback = sinon.spy();

const fn = debounce(callback, 100, true);

fn();
assert.strictEqual(callback.callCount, 1, 'Callback should be triggered immediately');

clock.tick(100);
assert.strictEqual(callback.callCount, 1, 'Callback should not be triggered again after wait time');

clock.restore();
});

await t.test('should execute immediately when immediate is in options object', async () => {
clock = sinon.useFakeTimers();
const callback = sinon.spy();

const fn = debounce(callback, 100, {immediate: true});

fn();
assert.strictEqual(callback.callCount, 1, 'Callback should be triggered immediately');

clock.tick(100);
assert.strictEqual(callback.callCount, 1, 'Callback should not be triggered again after wait time');

clock.restore();
});

await t.test('should not execute immediately when immediate is false', async () => {
clock = sinon.useFakeTimers();
const callback = sinon.spy();

const fn = debounce(callback, 100, {immediate: false});

fn();
clock.tick(50);
assert.strictEqual(callback.callCount, 0, 'Callback should not be triggered immediately');

clock.tick(50);
assert.strictEqual(callback.callCount, 1, 'Callback should be triggered after wait time');

clock.restore();
});
});

0 comments on commit 60a50c4

Please sign in to comment.