One-off event listeners in JavaScript

Event listeners in JavaScript

Before explaining what one time event listeners are, we have to first understand what events are and what event listeners are in JavaScript. If you know these concepts, feel free to skip this section and move to the next section which explains one time event listeners.

Events and Event Listeners

Events are at the heart of the JavaScript language. Most of the interactive elements we see on modern websites are implemented by attaching listeners(piece of code that listens to an event and gets executed) with the events.

According to MDN web docs, this is what events are:

Events are actions or occurrences that happen in the system you are programming, which the system tells you about so you can respond to them in some way if desired.

But wait, what does it mean?

Let’s break it down, it says an action or occurrence that happened in the system we are programming. In the context of the web, the system is our browser context and actions are either of user inputs, user actions or browser actions. Whenever any of the above types of event happen, the browser will notify that the event has occurred, and if there is any callback it should be executed. Some examples of events are:

  • User clicks on a button
  • User hovers on a DOM element
  • The browser has gained access to the Internet (online) or lost access (offline)

In general, events are nothing but a “signal” sent to notify that something happened in the system(browser in our case). Each event is represented by an object which is based on the Event interface including some additional properties about the particular event.

Event listeners or handlers are a way to say to the browser that — “run this block of code when this event occurs”. We can implement event handlers in the following two ways:

  1. Declaring an attribute on the HTML element we want to handle the event on. This works for most of the events. The attribute name should be same as the name of the event with an “on” prefix (e.g for click it will be onclick).
    Let’s see an example for this approach, head over to the HTML tab so see the source code. It consists of a button with an onclick attribute to show an alert. When you click the button, it will pop an alert saying “Thanks for clicking!”.

2. The second way is to call the addEventListener() method on the object which we want to listen events on. Just like the previous example, here also we have a button which says “Click me” and upon clicking it the browser gives an alert saying “Thanks for clicking”. Now, this time we are not embedding the handler in the HTML, but we are attaching an anonymous function to the clickButton button object in our JavaScript code. The benefit of this approach is that the listeners can later be changed (cannot be done in HTML attributes) and it makes the code more robust. Run the following example and see the result.

The addeventListener() method takes two main arguments along with some optional arguments. The first argument is a string describing the name of the event to be handled. The second one is the listener object(either a function or an object implementing EventListener interface). We will discuss the optional arguments in the next section.

Now that you know what events and event listeners are, let’s see what one time event listeners are.

One time event listeners

Event listeners are great, addEventListener() is used everywhere. But, there is a problem. The listener gets executed every time the event is fired. We may not want this to happen in each and every scenario.

Confused? Let’s take an example and understand why we need one time event listeners.

Suppose you have a website showing profile of different people each having their own profile picture. As there are many profiles, you want to show only the profile pictures in a grid so that it looks good.
Now, whenever a user clicks on a picture, a description pops out with the profile information of that person. If the same picture is clicked again, the listener will get executed again. And again and again. The description will pop out again and again, giving a not so good user experience. This is a big problem.
Another scenario like this can be the user clicking on a “More” button which retrieves a content description via the network and renders to the browser. If the user clicks on the button multiple times, it will try to fetch the network multiple times ignoring the previous responses, slowing down the performance which is again a bad user experience.

To solve this issue, there is a neat way to create one time event listeners using the removeEventListener() method. It is called with similar arguments as addEventListener() , but it removes a listener. Note that we will have to pass the same function value to removeEventListener() as passed in addEventListener() for it to actually work, otherwise it won’t work and you will just keep on debugging what wrong has happened. This means we will have to name the function explicitly and then pass the name to both the methods. Let’s see a code example to do this, we’ll be using the same example we have used in the last section.

As you can see, it only gives the alert for the first click. The function popAlert() removes the listener explicitly in the function body, making it disappear after the first click. These types of event handlers are called self removing event handlers. This is the most common way to create one time event listeners.
Apart from this we can also define a closure to serve this purpose, this way you will not have to define self removing event handlers again and again. We will create one function wrapper and use it everywhere. Let’s see an example how this can be done:

As you saw, we have defined a function wrapper named createOneTimeListener which takes three arguments namely element, event and listener. element is the HTML node, event is the name of the event and listener is the listener object. This approach saves our time by defining a reusable function that can be used for creating one time event listeners for any type of nodes or events.

Both of the above ways are clean and works as expected, but there is even an easier way to accomplish the same functionality in modern browsers. If you remember, we have talked about the optional parameters of addEventListener() method in this post earlier. We can use this optional parameter to create one-off listeners. There are two optional parameters namely options and useCapture for addEventListener(). useCapture is a boolean value indicating whether to use event capturing or not. The options parameter is an object that specifies configurations about the event listener. This allows us to configure the event listener with a once option to use it just for a single time. This is a cleaner approach and also we don’t have to keep track of the element or node. Let’s see an example:

As you saw this implements the same functionality with much fewer lines of code. Internally this works exactly same as removeEventListener(). If you have used jQuery before, you will find this similar to the .one() method, this being available to vanilla JS. Most modern browsers now support this feature, see here.

That’s it! Now you have the power of creating one time event listeners in your armory. If you liked the post, clap for me to let me know it was useful.

--

--