Files
30-seconds-of-code/snippets/js/s/execute-event-handler-once.md
2023-05-18 23:24:53 +03:00

63 lines
2.3 KiB
Markdown

---
title: How can I execute an event handler at most once?
shortTitle: Execute event handler only once
type: question
language: javascript
tags: [browser,event]
cover: dog-waiting
excerpt: Learn how to attach an event handler to events that is executed at most once in this JavaScript article.
dateModified: 2021-06-12T19:30:41+03:00
---
### jQuery
Back in the day when jQuery was all the rage, we would usually use [`$.one()`](https://api.jquery.com/one/) to create an event handler that would execute at most once for a given event per element. A simple example would be as follows:
```html
<button id="my-btn">Click me!</button>
```
```js
$('#my-btn').one('click', () => {
console.log('Hello!'); // 'Hello!' will only be logged on the first click
});
```
### Using a flag
However, jQuery seems to have fallen out of favor lately and thus many developers have resorted to writing their version of `$.one()`. An implementation could look like this:
```js
const listenOnce = (el, evt, fn) => {
let fired = false;
el.addEventListener(evt, (e) => {
if (!fired) fn(e);
fired = true;
});
};
listenOnce(
document.getElementById('my-btn'),
'click',
() => console.log('Hello!')
); // 'Hello!' will only be logged on the first click
```
In this implementation, we use a flag, `fired`, to check if the event has been triggered before and only execute the passed callback, `fn`, the first time the event is triggered. There are some details that we might have omitted such as removing the listener, but overall this is a reasonably solid implementation.
### Event listener options
If you are targeting modern browsers (i.e. not IE), [`EventTarget.addEventListener()`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) has introduced the `options` object parameter, which allows us to pass a few different flags, one of which is `once`. Setting `once` to `true` results in the exact same behavior as the snippet above with minimal effort.
Here's one way to write the previous snippet using `once`, which also happens to be how we implemented the latest version of the [listenOnce snippet](/js/s/listen-once):
```js
const listenOnce = (el, evt, fn) => el.addEventListener(evt, fn, { once: true });
listenOnce(
document.getElementById('my-btn'),
'click',
() => console.log('Hello!')
); // 'Hello!' will only be logged on the first click
```