This repository has been archived by the owner on Feb 20, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 603
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(debounce): add 'debounce' function (#191)
Added a debounce function to prevent multiple function calls at a time Closes: #190
- Loading branch information
1 parent
7808a04
commit 18379d4
Showing
3 changed files
with
111 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
export default debounce | ||
|
||
/** | ||
* Original Source: https://stackoverflow.com/questions/24004791/can-someone-explain-the-debounce-function-in-javascript | ||
* This method will prevent functions to be called repeatedly | ||
* @param {Function} func Function to debounce | ||
* @param {Number} [delay=0] The number of milliseconds to delay the function call | ||
* @param {Boolean} [immediate=false] | ||
* Weather to call the function and then wait or vice versa | ||
* @returns {Function} Returns the new debounced function. | ||
* @example | ||
* // Log the event after 1000ms of the last call | ||
* const debounced = debounce(console.log, 1000) | ||
* window.addEventListener('keyup', debounced) | ||
* | ||
* // Log the event immediately and wait 1000ms for the next call | ||
* const debounced = debounce(console.log, 1000, true) | ||
* window.addEventListener('keyup', debounced) | ||
* | ||
* // If 'delay' is falsy (except for 0), the function will not be debounced | ||
* const debounced = debounce(console.log) | ||
* window.addEventListener('keyup', debounced) | ||
*/ | ||
function debounce(func, delay, immediate) { | ||
let timeout | ||
if (typeof func !== 'function') { | ||
throw new TypeError('Expected a function') | ||
} | ||
return (...args) => { | ||
const callNow = immediate && !timeout | ||
if (!delay && delay !== 0) { | ||
func(...args) | ||
} else { | ||
clearTimeout(timeout) | ||
|
||
timeout = setTimeout(() => { | ||
timeout = null | ||
if (!immediate) { | ||
func(...args) | ||
} | ||
}, delay) | ||
|
||
if (callNow) { | ||
func(...args) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import test from 'ava' | ||
import {debounce} from '../src' | ||
|
||
let counter = 0 | ||
function incr() { | ||
return counter++ | ||
} | ||
|
||
function delay(ms) { | ||
return new Promise(resolve => { | ||
setTimeout(() => resolve(), ms) | ||
}) | ||
} | ||
|
||
test.beforeEach(t => { | ||
counter = 0 | ||
t.is(counter, 0) | ||
}) | ||
|
||
test('Throws error if first arg is not a function', t => { | ||
const error = t.throws(() => debounce('hello'), TypeError) | ||
t.is(error.message, 'Expected a function') | ||
}) | ||
|
||
test('Should immediately return value', t => { | ||
const debounced = debounce(incr) | ||
|
||
debounced() | ||
t.is(counter, 1) | ||
debounced() | ||
t.is(counter, 2) | ||
debounced() | ||
t.is(counter, 3) | ||
}) | ||
|
||
test.serial('Should resolve after 50ms', async t => { | ||
const wait = 50 | ||
const debounced = debounce(incr, wait) | ||
|
||
debounced() | ||
t.is(counter, 0) | ||
debounced() | ||
t.is(counter, 0) | ||
|
||
await delay(wait + 1) | ||
t.is(counter, 1) | ||
}) | ||
|
||
test.serial('Should resolve immediately', async t => { | ||
const wait = 50 | ||
const debounced = debounce(incr, wait, true) | ||
|
||
debounced() | ||
t.is(counter, 1) | ||
debounced() | ||
t.is(counter, 1) | ||
|
||
await delay(wait + 1) | ||
debounced() | ||
t.is(counter, 2) | ||
}) |