Skip to content

Commit

Permalink
feat(fn): support debounce cancel and flushing
Browse files Browse the repository at this point in the history
This adds the `cancel` and `flush` APIs to debounce to better control
the internal behavior.
  • Loading branch information
nikku authored and fake-join[bot] committed Aug 30, 2021
1 parent 51443fe commit b4ce77e
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 9 deletions.
36 changes: 29 additions & 7 deletions lib/fn.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/**
* Debounce fn, calling it only once if
* the given time elapsed between calls.
* Debounce fn, calling it only once if the given time
* elapsed between calls.
*
* Lodash-style the function exposes methods to `#clear`
* and `#flush` to control internal behavior.
*
* @param {Function} fn
* @param {Number} timeout
Expand All @@ -16,27 +19,42 @@ export function debounce(fn, timeout) {

let lastNow;

function fire() {
function fire(force) {

let now = Date.now();

let scheduledDiff = (lastNow + timeout) - now;
let scheduledDiff = force ? 0 : (lastNow + timeout) - now;

if (scheduledDiff > 0) {
return schedule(scheduledDiff);
}

fn.apply(lastThis, lastArgs);

timer = lastNow = lastArgs = lastThis = undefined;
clear();
}

function schedule(timeout) {
timer = setTimeout(fire, timeout);
}

return function(...args) {
function clear() {
if (timer) {
clearTimeout(timer);
}

timer = lastNow = lastArgs = lastThis = undefined;
}

function flush() {
if (timer) {
fire(true);
}

clear();
}

function callback(...args) {
lastNow = Date.now();

lastArgs = args;
Expand All @@ -46,8 +64,12 @@ export function debounce(fn, timeout) {
if (!timer) {
schedule(timeout);
}
};
}

callback.flush = flush;
callback.cancel = clear;

return callback;
}

/**
Expand Down
42 changes: 40 additions & 2 deletions test/fn.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ describe('fn', function() {
});


it('should not #clearTimeout', function() {
it('should not repetitively call #clearTimeout', function() {

let callback = sinon.spy();
let debounced = debounce(callback, 100);
Expand All @@ -147,7 +147,45 @@ describe('fn', function() {

// then
expect(callback).to.have.been.calledOnce;
expect(clearTimeout).not.to.have.been.called;
expect(clearTimeout).to.have.been.calledOnce;
});


it('should #cancel', function() {

var callback = sinon.spy();
var debounced = debounce(callback, 100);

// when
debounced();
debounced.cancel();

// debounce timer elapsed
clock.tick(101);

// then
expect(callback).not.to.have.been.called;
});


it('should #flush', function() {

var callback = sinon.spy();
var debounced = debounce(callback, 100);

// when
debounced();
debounced.flush();

// then
expect(callback).to.have.been.calledOnce;

// but when
// debounce timer elapsed
clock.tick(101);

// then
expect(callback).to.have.been.calledOnce;
});

});
Expand Down

0 comments on commit b4ce77e

Please sign in to comment.