In the previous article in this series, we looked at a practical use of closures called memoization. In this post we’re going to briefly look at closures in action through a debounce function.
A debounce delays the processing of a function for a certain amount of time. It can be very useful with things like forms, buttons, or mouse events–anytime there is a lot of user input possible. It can help prevent rapid fire re-rendering of the DOM by introducing a “cooldown” period, to use gaming terminology.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Practice</title>
</head>
<body>
<button id="button">Click Me</button>
<script>
const debounce = (func, delay) => {
let inDebounce
return function () {
const context = this
const args = arguments
clearTimeout(inDebounce)
inDebounce = setTimeout(() => func.apply(context, args), delay)
}
}
const button = document.getElementById('button')
button.addEventListener('click', debounce(() => {
console.log('Hey! It is', new Date().toUTCString())
}, 3000))
</script>
</body>
</html>
My goal here isn’t to teach you how to write the debounce. There’s plenty of resources (you could literally copy paste a generic debounce function, like I did here). More so, I want you to spot the closure in there and have that “ah-ha” moment. If you want a guide or to get in depth on this function, check out the [source] (https://codeburst.io/throttling-and-debouncing-in-javascript-b01cad5c8edf) I used.
The key here, from a closure standpoint, is our inDebounce
variable. As a closure, returned function “remembers” whether or not it the variable is running a timeout. If we fire it off while it’s still in the timeout, it will clearTimeout
, thus restarting it.
Another instance of a closure in action.
Have you guys used debounces before? Are there different variations or use cases where its been super helpful?