3
\$\begingroup\$

I am trying to implement throttle function in vanilla JavaScript. I have seen other implementations on the web, but the way I have implemented it is more understandable for myself. I was wondering if any of you experts can take a look and let me know if I am missing some thing. It seems to be working fine but I am not sure the way I handle it is the correct.

HTML:

<html>

  <head>

  </head>

  <body>
    <div id='move'>

    </div>
    <div id='result'>

    </div>
  </body>

JS:

var area;
var result;

function init() {
  area = document.querySelector('#move');
  area.addEventListener('mousemove', trottle);
  result = document.querySelector('#result');
}

function updateResult(event) {
  let xCordinate = event.clientX;
  let yCordinate = event.clientY;
  result.textContent = `${xCordinate} , ${yCordinate}`;
}



function trottle(event) {
  updateResult(event);
  let element = event.target
  element.removeEventListener('mousemove', trottle);
  setTimeout(function() {
    element.addEventListener('mousemove', trottle);
  }, 2000)

}

init();
\$\endgroup\$
1
\$\begingroup\$

Overall the code appears easy to read, and does what you say it does.

General comments:

  • The name of the throttle function is misspelled (trottle versus throttle). Not a show stopper, but does make it harder to read.

  • I see a number of ECMA script language features being used, but the old function() { ... } style is being used for the callback in setTimeout. Consider using the more concise "arrow function expression" (e.g. lambda expression) syntax instead:

    setTimeout(() => element.addEventListener('mousemove', throttle), 2000);
    

Code reusability and variable scope

  • Two global variables are being declared, and really should not exist in the global scope. Consider using an Immediately Invoked Function Expression (IIFE) to hide them:

    (() => {
        let area;
        let result;
    
        ...
    })();
    

    Or you can use a build tool like Grunt to automatically wrap this script in an IIFE.

  • Other events are just as "spammy" as the mousemove event. The "scroll" event is just as bad, and this could be useful for that as well. Consider parameterizing the event that is being throttled.

  • Same thing with the updateResult function. It could be parameterized as a callback function.

  • Parameterizing the frequency of the throttling would be easy, and a good idea as well.

  • The CSS selectors used to target the element whose events are being throttled is the last thing that needs to be parameterized in order to make this truly reusable.

Given this, a function signature like the following would probably allow you to fix all the issues, including leaking variables to the global scope:

function throttleEvent(element, eventName, frequency, callback) {
    ...
}

And would be used like this:

let area = document.querySelector("#move");
let result = document.querySelector('#result');
let updateResult = (event) => {
    result.textContent = `${event.clientX} , ${event.clientY}`;
};

throttleEvent(area, "mousemove", 2000, updateResult);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.