Part of a small project I'm working on is the user being able to add tags to items, similarly to StackOveflow. These tags are stored in a database, so obviously I need to call an API to fetch matching tags. To prevent my API from being hit too often, I want to add a debounce method, however none of the examples I've found seem to work. Even lodash's debounce
method doesn't work.
I'm currently trying this debounce method in Vue3;
const debounce = (fn: Function, delay: number): Function => {
let timeout: NodeJS.Timeout;
return (...args: any): void => {
clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
};
onMounted(() => {
debounce(() => console.log('hello'), 500);
});
The debounce
method itself is called just fine, but the provided callback isn't. Same goes for lodash's debounce
method, the method itself is called but whatever method I pass isn't.
Am I missing something obvious?
Edit: I was indeed missing something obvious. The actual use case was this method (no API call yet, wanted to get the debounce
method working first);
const handleTagKeyUp = (event: KeyboardEvent): void => {
filteredTags.value = [];
const value = inputTags.value.trim();
if (event.code === 'Enter') {
addTag(value);
return;
}
if (value.length < 3) {
return;
}
const selectedTagNames = selectedTags.value.map((t: Tag) => t.name.toLowerCase());
filteredTags.value = props.tags.filter((t: Tag) => t.name.toLowerCase().includes(value) && ! selectedTagNames.includes(t.name.toLowerCase()));
};
which is called whenever the keyup
event is fired. Simply changing it to
const handleTagKeyUp = (event: KeyboardEvent): void => {
filteredTags.value = [];
const value = inputTags.value.trim();
if (event.code === 'Enter') {
addTag(value);
return;
}
if (value.length < 3) {
return;
}
findTags(value);
};
const findTags = debounce((value: string) => {
const selectedTagNames = selectedTags.value.map((t: Tag) => t.name.toLowerCase());
filteredTags.value = props.tags.filter((t: Tag) => t.name.toLowerCase().includes(value) && ! selectedTagNames.includes(t.name.toLowerCase()));
}, 500);
fixed the issue.
CodePudding user response:
This isn't how debounce
is used. Think about it: how would debounce
respond to multiple calls to onMounted
if a new debounce
is created every time onMounted
is called?
debounce
returns a function that must be called, and calls to that returned function are denounced:
// In some scope. I don't know Vue.js
const debounced = _.debounce(() => console.log('hello'), 500);
onMounted(() => {
debounced()
});