Optimizing JavaScript Event Listeners for Performance

Optimizing JavaScript Event Listeners for Performance

While I am writing this, there are so many listeners are listening for an event on your website.

Why we add them, it is not a concert of this post, in this article I am going to write more about how we can add them.

If you are worried that do you need that event listener or not, think this way that is it possible to handle it with CSS? if yes, do not hesitate to remove your event listener and do it in CSS.

What is an Event Listener?

An event listener is a procedure or function in a computer program that waits for an event to occur; that event may be a user clicking or moving the mouse, pressing a key on the keyboard, or an internal timer or interrupt. The listener is in effect a loop that is programmed to react to an input or signal.

window.addEventListener('resize', function, useCapture);
// OR
element.addEventListener(event, function, useCapture);
// With the addEventListener() method you can specify the propagation type by using the "useCapture" parameter

and for removing:

element.removeEventListener(event, function);

To continue this article I am going to explain different methods and patterns that can be used.

Event Delegation

(I have an article including this one here)

Event delegation promotes binding as few DOM event handlers as possible, since each event handler requires memory. For example, let’s say that we have an HTML unordered list we want to bind event handlers to. Instead of binding a click event handler for each list item (which may be hundreds for all we know), we bind one click handler to the parent unordered list itself.

// Get the element, add a click listener...
<ParentElementDOM>.addEventListener("click",function(e) {
  // e.target was the clicked element
  if (e.target && e.target.matches("a.classA")) {
    console.log("Anchor element clicked!");
  }
});

Debounce

There are several situations in JavaScript where you want a function that is bound to an event to fire only once after a specific amount of time has passed. Functions bound to the resize and scroll events are the typical candidates. Invoking a function every time one of these events fires will significantly impact performance. Enter the JavaScript debounce function.

var myEfficientFn = debounce(function() {
	// All the taxing stuff you do
}, 250);
function debounce(func, wait, immediate) {
	var timeout;
	return function() {
		var context = this, args = arguments;
		var later = function() {
			timeout = null;
			if (!immediate) func.apply(context, args);
		};
		var callNow = immediate && !timeout;
		clearTimeout(timeout);
		timeout = setTimeout(later, wait);
		if (callNow) func.apply(context, args);
	};
};
window.addEventListener('resize', myEfficientFn);

RequestAnimationFrame

If you have the urge to perform animations in Javascript, then you have probably used a setTimeout or setInterval to achieve this. This is bad for a whole number of reasons, the biggest one being they will suck performance from your visitors browser and flatten their little phone batteries.

function repeatOften() {
    // Do whatever  
    requestAnimationFrame(repeatOften); 
} 
requestAnimationFrame(repeatOften);

The benefits of requestAnimationFrame

  • They are browser optimised, so they can operate in most cases at 60fps
  • Animations taking place in inactive tabs are stopped. Meaning if a user navigates away from your tab and you have an animation, it releases the stronghold it has on the CPU.
  • Because of the performance, battery life and page responsiveness are better on low-end devices and mobile browsers.
function myFunc() {
    // Do whatever
    requestAnimationFrame(myFunc);
}
requestAnimationFrame(myFunc);

The idea is you call requestAnimationFrame initially to kickstart the process and then call the requestAnimationFrame from within the function being called thus creating a loop.

Throttling

Throttling is a straightforward reduction of the trigger rate. It will cause the event listener to ignore some portion of the events while still firing the listeners at a constant (but reduced) rate.

function throttle (callback, limit) {
  var wait = false;
  return function () {
    if (!wait) {
      callback.apply(null, arguments);
      wait = true;
      setTimeout(function () {
        wait = false;
      }, limit);
    }
  }
}
window.addEventListener('resize', throttle(function(e){console.log(e)}, 100));

If you are into knowing the difference between Throttling and Debouncing, Click here

Scroll Events with Passive Event Listeners

(I have an article about this one here)

It enable developers to opt-in to better scroll performance by eliminating the need for scrolling to block on touch and wheel event listeners.

document.addEventListener('wheel', (evt) => {   
   // ... do stuff with evt 
}, {   
   capture: true,   
   passive: true 
})

Conclusion

Knowing how to write JavaScript is not enough by itself, Learning CSS helps a lot to change so many things to have a smoother website.

But Keep it in mind if you wanted to write an Event Listener, develop it in an optimised way.

Source:


To view or add a comment, sign in

Insights from the community

Others also viewed

Explore topics