7

The new AbortController API in JavaScript allows us to remove multiple event listeners in one statement. So if we have 20 event listeners, we don't need to write 20 removeEventListener(); we can simply write controller.abort(); to remove them all.

Now, I'm wondering in what situations I'd be able to take advantage of this feature in a real application. I've never needed to remove a large number of event listeners at once.

(I already know that abort() can also be used to cancel a fetch request)

Thanks!

0

2 Answers 2

9

NEW ANSWER: The answer given below was based on the Mozilla MDN Documentation. After some research, I found that there is in fact a way to remove an event listener with the AbortController Constructor. It's a new chrome88 feature release (Jan 2021) and may not have full adoption across all browsers yet, so the preferred method is still the old answer below.

The AbortController method was tested and seems to work in chrome & edge as of 09/21.

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h3>🚀 Check the JS-Console</h3>
    <button class="button" name="button1">Btn 1</button>
    <button class="button" name="button2">Btn 2</button>
    <button class="button" name="button3">Btn 3</button>
    <button id="remove-btn">Remove Listener</button>
    <script src="script.js"></script>
</body>
</html>

JS

const buttons = document.getElementsByClassName('button');
const removeListenerBtn = document.getElementById('remove-btn');

const controller = new AbortController();

for (let element of buttons) {
    element.addEventListener(
        'click', 
        (event) => {
            console.log(event.target.name, "clicked")
        }, 
        { signal: controller.signal }
    )
}

removeListenerBtn.addEventListener("click", () => {
    controller.abort()
})

OLD ANSWER: The Abort Controller object is for aborting fetch calls, not for removing event listeners. If you need to remove multiple listener's here's one way of doing it.

This example grabs all DOM elements that contain the class def "button" then attaches an event listener using a for loop.

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h3>🚀 Check the JS-Console</h3>
    <button class="button" name="button1">Button 1</button>
    <button class="button" name="button2">Button 2</button>
    <button class="button" name="button3">Button 3</button>
    <button id="remove">Remove All Listeners</button>
    <script src="script.js"></script>
</body>
</html>

JS

const buttons = document.querySelectorAll('.button');
const removeListeners = document.getElementById('remove');

buttons.forEach(element => {
    element.addEventListener("click", doSomthing)
});

removeListeners.addEventListener("click", removeList)

function removeList(){
    buttons.forEach(element => {
        element.removeEventListener("click", doSomthing)
    });
}

function doSomthing(e){
    console.log(e.target.name, "clicked");
}
Sign up to request clarification or add additional context in comments.

3 Comments

@Monster Cat If this answers your question, can you please mark this as the answer?
Sorry, this doesn't answer my question. Abort controller can be used to remove event listeners too. And I wanted to know when it's preferred compared to the old approach. Thanks for the answer though I've upvoted your answer.
@MonsterCat I went ahead and updated my answer.
2

I use it in React to remove event listeners I added to the window or document objects inside an effect. This is useful because I don't have to make a separate event handler function just to later pass it inside removeEventListener(). Instead I can just use AbortController's abort() method to remove the event listener in the clean up function of useEffect.

e.g.

// react component code...

React.useEffect(() => {
    const { signal, abort } = new AbortController()

    window.addEventListener('mousemove', () => {
        // handle event here...
    }, { signal })

    return () => {
        abort()
    }
},[])

4 Comments

"I don't have to make a separate event handler function" - you're still creating the function. If you're talking about variables, notice that instead of making one variable to store the function, you're making two variables to store the signal and the abort method :-) Still, a valuable technique especially when installing multiple event handlers that all need to be cleaned up at the same time.
I think, you can't call abort() method directly, without using the AbortController instance. Correct usage might be abortContoller.abort() or bind the abort() function to AbortController instance..
Actually I have created the instance. It's just that I am de-structuring the abort method instead of assigning the instance to one variable. Are these two ways different?
They are different. I think you will get TypeError: Illegal invocation error. See why is javascript bind necessary

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.