🔍 Note at the bottom that there is some disagreement on terminology here 🔍

I was messing around with event listeners during a pairing session yesterday and thought it'd make a fun post. It started with this line of code:

enquirer.on(`prompt`, prompt => {
// some code here
})

In the above code, on uses an event listener. Let's talk about what that means and the various concepts at work.

An event

The first argument given to on is the string "prompt". This represents the event type, prompt.

At some point in our program the following code gets called.

enquirer.prompt()

When enquirer calls prompt, it fires that event type and our associated event listener takes notice!

Event listener

When the event we're listening for is fired, that triggers our event listener. The listener is the second argument we passed, our (currently empty) function.

Let's look at the function more closely.

prompt => {
// some code here
}

This function is a callback. Every time an event of type "prompt" fires, the callback will execute. Note that the callback takes a singular parameter, prompt. prompt is an object describing the event that occurred.

Where else does this exist?

Event listeners are a construct that exist throughout web development. You may be most familiar with them due to browser events.

For example, when a user clicks on a button, we can listen to a click event.

const button = document.getElementById('btn')
button.addEventListener('click', event => {
// some code here
})

However, this is not the only way to handle a click event.

Event handlers

Browsers support global event handlers for common events like click.

const button = document.getElementById('btn')
button.onclick = event => {
// some code here
}

Additionally, some elements have their own onevent attributes which can register an event handler directly.

<button onclick="handleClick()">Text</button>

What's the difference?

Event handlers appear to be the same as event listeners, but there is one main difference. When you use addEventListener you can execute multiple callbacks for a given event type, e.g. click.

const button = document.getElementById('btn')
button.addEventListener('click', event => {
console.log('First')
})
button.addEventListener('click', event => {
console.log('Second')
})
// First Second will get logged

When you use event handlers directly, only one function can be assigned.

const button = document.getElementById('btn')
button.onclick = event => {
console.log('First')
}
button.onclick = event => {
console.log('Second')
}
// only Second will get logged

What about React?

You might be wondering how this concept works inside a framework like React. As it turns out, the code you write looks a lot like our previous event handler examples.

<button onClick={handleClick}>Text</button>

There is a fair amount happening under the hood here, read synthetic events if you're interested in learning more. But the main takeaway is that React code more or less models onevent handler syntax. However, in situations where you need to handle DOM events that aren't provided by React, you can still use addEventListener.

All the pieces

That's a lot of different ways to handle events! So what's the takeaway?

  1. Using addEventListener you can listen to any event type and trigger a corresponding callback, called a listener.
  2. Alternatively, elements can take a function, called an event handler, directly as an attribute or property.
  3. For a given element, you can only have one event handler per event type, but you can have multiple event listeners.

Now, I have to add one caveat at the end of this. There is some disagreement as to whether the term event listener and event handler are interchangeable. As both reference the function that handles the event object itself. Even MDN seems to be inconclusive, calling the callback listener but using the term event handler in the section on listeners.

Despite that confusion, there are differences in both syntax and functionality between addEventListener and DOM onevent handlers.

Hopefully this post helped clarify the various Web APIs for handling events. Aren't browsers fun?!