shankar-kruthiventi
shankar-kruthiventi

Reputation: 83

debounce function not working in javascript

I'm having problem understanding why the below debounce code does not work?

you can see the below code in the following: link

`
HTML:

<input type="text" onkeyup="betterFunction(event)"/>

JS:

let newValue;
let counter = 0;
const getData = () => {
    // dummy call to API and get Data
    console.log("Fetching Data ..", newValue,counter++);
}

const debounce = function (fn, d) {
    let timer;
    return function () {
        clearTimeout(timer);
        timer = setTimeout(() => {
            fn();
        }, d);
   }
}

const betterFunction = ({target:{value}}) => {
    newValue=value;
    debounce(getData, 2000); // **line 1**. placing this line of code debouncing does not happen
  
    intermediate()  // **line 2**. replacing this line of code with the above line debouncing works
}

const intermediate = debounce(getData, 2000);

`

I understand that the debounce function returns another function which acts like a closure in JavaScript but why the above line 1 code does not work but the line 2 code works

Upvotes: 2

Views: 4774

Answers (2)

Yousaf
Yousaf

Reputation: 29282

debounce function returns a function which is never called when you call debounce as

debounce(getData, 2000);

dobounce function doesn't needs to return a function. You just need following steps to implement debounce function:

  1. Check if timer is undefined or not. If not, that means there's a timeout that we need to cancel.

  2. After that set a new timer by calling setTimeout() that calls the given function after specific amount of time.

Also, timer should not be a local variable because you don't want it to reset whenever debounce function is called.

let counter = 0;
let newValue;
let timer;

const getData = () => {
  console.log("Fetching Data ..", newValue, counter++);
}

const debounce = function(fn, d) {
  if (timer) {
    clearTimeout(timer);
  }

  timer = setTimeout(fn, d);
}

const betterFunction = (e) => {
  newValue = e.target.value;
  debounce(getData, 2000);
}
<input type="text" onkeyup="betterFunction(event)" />

If you don't want to declare timer as a global variable and want to return a function from debounce function, then you need to call the debounce function once initially and whenever keyup event fires on the input element, you call the function returned from the debounce function instead of calling the debounce function.

let counter = 0;
let newValue;

const getData = () => {
  console.log('Fetching Data ..', newValue, counter++);
};

const debounce = function(fn, d) {
  let timer;
  
  return function() {
    if (timer) {
      clearTimeout(timer);
    }

    timer = setTimeout(fn, d);
  };
};

const intermediate = debounce(getData, 2000);

const betterFunction = (e) => {
  newValue = e.target.value;
  intermediate();
};
<input type="text" onkeyup="betterFunction(event)" />

Upvotes: 7

ocean
ocean

Reputation: 186

i hope that what you want :

let counter = 0;
// you need to define timer and newValue here first
let timer , newValue;

// defining input as varible for good usage better than usage in html
var input = document.querySelector("#inp");

const getData = () => {
    // increment first better than in console :)
    counter+=1;
    console.log("Fetching Data .." , newValue , counter);

    // as last step clear timer for next timeout
    clearTimeout(timer);
}

// givin value direct to timer directlly worked better than return
const debounce = function (fn, d) {
    timer = setTimeout(fn, d);
}


const betterFunction = () => {
    // newvalue must equal input value
    newValue = input.value;
    // and then calling debounce as last step
    debounce(getData, 2000);
}

// here giving onkeyup event to input for getting values and start working :)
input.onkeyup = betterFunction;

Upvotes: 0

Related Questions