Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

abordolo's avatar

Debounce in watch

Hi,

I am implementing search in a data table. For this, I have a ref 'searchString' which I am watching.

// imports
import { ref, watch } from 'vue';
import debounce from 'lodash/debounce';

// search string
const searchString = ref('');
const searching = ref(false);

// search
const search = () => {
  console.log('Searching with: ', searchString.value);
};

// watch search string
watch(searchString, debounce(search, 500));

This works fine. But with the following watch method, it is not working.

// watch search string
watch(searchString, () => {
  console.log('Inside watch');
  debounce(search, 500);
});

I started with the code that is not working and worked towards the working code. But I am wondering, why it is not working in the second piece of code.

The following watch method works as well without debounce:

// watch search string
watch(searchString, () => {
  console.log('Inside watch');
  search();
});

When debounce is within a callback, it is not working. Could anyone please help me knowing why.

Thanks in advance.

0 likes
2 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

The issue you're encountering is due to how the debounce function from Lodash works. When you call debounce(search, 500) inside the watch callback, you're creating a new debounced function every time the searchString changes. This means that the debounced function is not retaining its state between calls, and thus, it never actually gets to the point where it executes the search function.

In your first example, you correctly create a single debounced function outside of the watch callback, which retains its state and works as expected. Here's a breakdown of why the second approach doesn't work and how to fix it:

Why the Second Approach Doesn't Work

  1. New Debounced Function Each Time: Every time searchString changes, a new debounced function is created. This new function has its own timer, which starts fresh each time, and thus, it never reaches the point where it executes the search function.

  2. State Retention: Debounced functions need to retain their state (like the timer) across multiple calls to work correctly. Creating a new debounced function each time prevents this.

Solution

To fix this, you should create the debounced function once, outside of the watch callback, and then call this debounced function inside the watch callback. Here's how you can do it:

// imports
import { ref, watch } from 'vue';
import debounce from 'lodash/debounce';

// search string
const searchString = ref('');
const searching = ref(false);

// search
const search = () => {
  console.log('Searching with: ', searchString.value);
};

// Create a debounced version of the search function
const debouncedSearch = debounce(search, 500);

// watch search string
watch(searchString, () => {
  console.log('Inside watch');
  debouncedSearch();
});

Explanation

  • Debounced Function Creation: By creating debouncedSearch outside of the watch callback, you ensure that the same debounced function is used every time searchString changes. This allows the debounce logic to work correctly, as it can maintain its internal state (like the timer) across multiple invocations.

This approach will ensure that your search function is debounced correctly, preventing it from being called too frequently as the user types.

1 like

Please or to participate in this conversation.