Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call original debounced function with proper "this" context #456

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions lib/throttle.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,27 @@ const throttle = (timeout, fn, ...args) => {
};

// Debounce function, delayed execution
// Signature: timeout, fn, ...args
// Signature: timeout, fn, ...presetArgs
// timeout - <number>, msec
// fn - <Function>, to be debounced
// args - <Array>, arguments for fn, optional
const debounce = (timeout, fn, ...args) => {
// presetArgs - <Array>, pre-populated arguments for fn, optional
const debounce = (timeout, fn, ...presetArgs) => {
let timer;

const debounced = () => (args ? fn(...args) : fn());

const wrapped = () => {
if (timer) clearTimeout(timer);
timer = setTimeout(debounced, timeout);
return function (...newArgs) {
const args = newArgs.length !== 0 ? newArgs : presetArgs;
if (
newArgs.length === 0 &&
timer !== undefined &&
timer.refresh !== undefined
) {
// if possible, refresh the timer without
// allocating a new JavaScript object
timer.refresh();
} else {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), timeout);
}
};

return wrapped;
};

const FN_TIMEOUT = 'Metasync: asynchronous function timed out';
Expand Down
42 changes: 12 additions & 30 deletions test/examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -399,43 +399,25 @@ metatests.test('trottle', (test) => {
metatests.test('debounce', (test) => {
const expectedResult = ['E', 'I'];
const result = [];
let state;

const fn = () => {
result.push(state);
const fn = (arg) => {
result.push(arg);
};

const f1 = metasync.debounce(500, fn, ['I']);
const f1 = metasync.debounce(500, fn);

// to be called one time (E)
state = 'A';
f1();
state = 'B';
f1();
state = 'C';
f1();
state = 'D';
f1();
state = 'E';
f1();
f1('A');
f1('B');
f1('C');
f1('D');
f1('E');

// to be called one time (I)
setTimeout(() => {
state = 'F';
f1();
}, 600);
setTimeout(() => {
state = 'G';
f1();
}, 700);
setTimeout(() => {
state = 'H';
f1();
}, 1000);
setTimeout(() => {
state = 'I';
f1();
}, 1100);
setTimeout(() => f1('F'), 600);
setTimeout(() => f1('G'), 700);
setTimeout(() => f1('H'), 1000);
setTimeout(() => f1('I'), 1100);

setTimeout(() => {
test.strictSame(result, expectedResult);
Expand Down
42 changes: 41 additions & 1 deletion test/throttle.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ metatests.test('throttle without arguments for function', (test) => {
test.strictSame(callCount, 1);
});

metatests.test('debounce', (test) => {
metatests.test('debounce with pre-populated arguments', (test) => {
let count = 0;

const fn = (arg1, arg2, ...otherArgs) => {
Expand All @@ -85,6 +85,22 @@ metatests.test('debounce', (test) => {
test.strictSame(count, 0);
});

metatests.test('debounce with arguments', (test) => {
let count = 0;

const fn = (...args) => {
test.strictSame(args, [1, 2, 3]);
count++;
test.end();
};

const debouncedFn = metasync.debounce(1, fn);

debouncedFn(0, 1, 2);
debouncedFn(1, 2, 3);
test.strictSame(count, 0);
});

metatests.test('debounce without arguments for function', (test) => {
let count = 0;

Expand All @@ -101,6 +117,30 @@ metatests.test('debounce without arguments for function', (test) => {
test.strictSame(count, 0);
});

metatests.test('debounce with proper "this" binding', (test) => {
let count = 0;
let originalThis;

class DebounceTest {
constructor() {
this.debouncedMethod = metasync.debounce(1, this.originalMethod);
originalThis = this;
}

originalMethod(...args) {
test.strictSame(args, []);
test.strictSame(this, originalThis);
count++;
test.end();
}
}

const debounceTestInstance = new DebounceTest();
debounceTestInstance.debouncedMethod();
debounceTestInstance.debouncedMethod();
test.strictSame(count, 0);
});

metatests.test('timeout with sync function', (test) => {
const syncFn = (callback) => callback(null, 'someVal');
metasync.timeout(1, syncFn, (err, res, ...args) => {
Expand Down