Home > Blockchain >  Callback passed to debounce method not called
Callback passed to debounce method not called

Time:12-25

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()
});
  • Related