2024-04-15 Debounce
Debouncing is a technique to delay and coalesce time-consuming tasks in response to events that occur frequently. For example, by debouncing input into a search box, instead of sending a request on every keystroke you can wait until the user stops typing. This reduces load on the server and may improve the user experience.
Framework doesn’t have a built-in function to debounce input, but you can implement one by writing a generator. Here we’ll use Generators.observe to listen to input events on the given input element, emitting the new value no more than once a second.
const input = debounce(display(Inputs.text({placeholder: "Type some text…"})));
input // the current value; note that it updates slowly
The debounce helper is imported from a debounce.js file which contains:
import {Generators} from "npm:@observablehq/stdlib";
export function debounce(input, delay = 1000) {
return Generators.observe((notify) => {
let timer = null;
let value;
// On input, check if we recently reported a value. If we did, do nothing and wait for a delay;
// otherwise, report the current value and set a timeout.
function inputted() {
if (timer !== null) return;
notify(value = input.value);
timer = setTimeout(delayed, delay);
}
// After a delay, check if the last-reported value is the current value. If it’s not, report
// the new value.
function delayed() {
timer = null;
if (value === input.value) return;
notify(value = input.value);
}
input.addEventListener("input", inputted), inputted();
return () => input.removeEventListener("input", inputted);
});
}
It can be imported like so:
import {debounce} from "./debounce.js";
If you’d prefer to use lodash instead, you could implement debounce like so:
function debounce(input, delay = 1000) {
return Generators.observe((notify) => {
notify = _.debounce(notify, delay);
const inputted = () => notify(input.value);
input.addEventListener("input", inputted), inputted();
return () => input.removeEventListener("input", inputted);
});
}