Skip to content
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