DEV Community

indrasisdatta
indrasisdatta

Posted on

Vanilla JS Debounce using API example

Understanding Debounce:

Debouncing refers to a technique used to optimize the execution of a function by delaying its invocation until a certain amount of time has passed. The below example demonstrates the use of debouncing in a products search functionality.

In this search products example, it's supposed to return API data based on search input. To reduce the no. of API calls, searchProducts() is called after a slight delay.

HTML:

<!-- Search product -->
<input id="product" />

<!-- Show search results -->
<div id="search-result">
</div>
Enter fullscreen mode Exit fullscreen mode

JS:

The delayWrapper function is a higher-order function that creates a debounced version of the provided function func. It sets up a timer to delay the execution of func until the specified timeout period has passed.

const delayWrapper = (func, timeout) => {
    let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func(...args)
    }, timeout);
  }
}
Enter fullscreen mode Exit fullscreen mode

The delayedCallvariable is assigned the debounced version of the searchProductsfunction, created using delayWrapper. It has a delay of 500 milliseconds (0.5 seconds).

const delayedCall = delayWrapper(searchProducts, 500);
Enter fullscreen mode Exit fullscreen mode

The searchProducts function uses the provided search query q to fetch data from an API endpoint using fetch. The retrieved data is stored in products variable.

const searchProducts = async (q) => {
  let products = [];
  try {
    console.log(`Search param: ${q}`)
    const response = await fetch(`https://dummyjson.com/products/search?q=${q}`);
    const data = await response.json();
    products = data.products;
  } catch (e) {
    console.error('Error found: ', e);
  }
  renderProducts(products);  
}
Enter fullscreen mode Exit fullscreen mode

The renderProductsfunction takes an array of products as a parameter and generates HTML based on the products. If there are products, it creates an unordered list ul with list items li representing each product's title.

const renderProducts = (products) => {
    let searchHtml = '';
    if (products.length > 0) {
        searchHtml = '<ul>';
        products.map(prod => {
            searchHtml += `<li>${prod.title}</li>`;
        })
        searchHtml += '</ul>';
    }
    console.log('Search html', searchHtml)
    document.getElementById('search-result').innerHTML = searchHtml;
}

Enter fullscreen mode Exit fullscreen mode

Full JS Code:

document.getElementById('product').addEventListener('keyup', (e) => {
    delayedCall(e.target.value);
})


const searchProducts = async (q) => {
    let products = [];
    try {
        console.log(`Search param: ${q}`)
        const response = await fetch(`https://dummyjson.com/products/search?q=${q}`);
        const data = await response.json();
        console.log('API data', data)
        products = data.products;
    } catch (e) {
        console.error('Error found: ', e);
    }
    renderProducts(products);
}

const delayWrapper = (func, timeout) => {
    let timer;
    return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => {
            func(...args)
        }, timeout);
    }
}

const delayedCall = delayWrapper(searchProducts, 1500);

const renderProducts = (products) => {
    let searchHtml = '';
    if (products.length > 0) {
        searchHtml = '<ul>';
        products.map(prod => {
            searchHtml += `<li>${prod.title}</li>`;
        })
        searchHtml += '</ul>';
    }
    console.log('Search html', searchHtml)
    document.getElementById('search-result').innerHTML = searchHtml;
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)