Skip to content

Commit

Permalink
Document abortable event listeners
Browse files Browse the repository at this point in the history
This patch includes the following changes:

- Document the "signal" parameter for the addEventListener() options object
- “Add an abortable listener” example code added to addEventListener() article
- Add a similar simple example code to he “Introduction to events” guide
- In both “Introduction to events” guide and removeEventListener() article,
  add prose mentions that you can pass an AbortSignal to an addEventListener()
  call, and abort/cancel/remove the listener by calling abort() on the
  controller owning the AbortSignal.
  • Loading branch information
sideshowbarker committed Feb 28, 2021
1 parent f3b4a9b commit 93fef08
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 3 deletions.
12 changes: 10 additions & 2 deletions files/en-us/learn/javascript/building_blocks/events/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,17 @@ <h3 id="adding_and_removing_event_handlers">Adding and removing event handlers</

<pre class="brush: js">btn.removeEventListener('click', bgChange);</pre>

<p>This isn't significant for simple, small programs, but for larger, more complex programs it can improve efficiency to clean up old unused event handlers. Plus, this allows you to have the same button performing different actions in different circumstances — all you have to do is add or remove event handlers as appropriate.</p>
<p>Event handlers can also be removed by passing an {{domxref("AbortSignal")}} to {{domxref("EventTarget/addEventListener()", "addEventListener()")}} and then, later, calling {{domxref("AbortController/abort()", "abort()")}} on the controller owning the <code>AbortSignal</code>. For example, to add an event handler that we can remove with an <code>AbortSignal</code>:</p>

<p>Second, you can register multiple handlers for the same listener. The following two handlers wouldn't both be applied:</p>
<pre class="brush: js">const controller = new AbortController();
btn.addEventListener('click', function() {
var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
document.body.style.backgroundColor = rndCol;
}, { signal: controller.signal }); // pass an AbortSignal to this handler</pre>

<p>Then the event handler created by the code above can be removed like this:</p>

<pre class="brush: js">controller.abort(); // removes any/all event handlers associated with this controller</pre>

<p>For simple, small programs, cleaning up old, unused event handlers isn’t necessary — but for larger, more complex programs, it can improve efficiency. Plus, the ability to remove event handlers allows you to have the same button performing different actions in different circumstances — all you have to do is add or remove handlers.</p>

Expand Down
40 changes: 40 additions & 0 deletions files/en-us/web/api/eventtarget/addeventlistener/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ <h3 id="Parameters">Parameters</h3>
does call <code>preventDefault()</code>, the user agent will do nothing other than
generate a console warning. See <a href="#improving_scrolling_performance_with_passive_listeners">Improving scrolling performance with
passive listeners</a> to learn more.</dd>
<dt><code>signal</code></dt>
<dd>An {{domxref("AbortSignal")}}. The listener will be removed when the given <code>AbortSignal</code>’s {{domxref("AbortController/abort()", "abort()")}} method is called.</dd>
<dt>{{non-standard_inline}} <code>mozSystemGroup</code></dt>
<dd>A {{jsxref("Boolean")}} indicating that the listener should be added to the
system group. Available only in code running in XBL or in the
Expand Down Expand Up @@ -249,6 +251,44 @@ <h4 id="Result">Result</h4>

<p>{{EmbedLiveSample('Add_a_simple_listener')}}</p>

<h3 id="add_a_abortable_listener">Add an abortable listener</h3>

<p>This example demonstrates how to add an <code>addEventListener()</code> that can be aborted with an {{domxref("AbortSignal")}}.</p>

<h4 id="HTML">HTML</h4>

<pre class="brush: html">&lt;table id="outside"&gt;
&lt;tr&gt;&lt;td id="t1"&gt;one&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td id="t2"&gt;two&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
</pre>

<h4 id="JavaScript">JavaScript</h4>

<pre class="brush: js">// Add an abortable event listener to table
const controller = new AbortController();
const el = document.getElementById("outside");
el.addEventListener("click", modifyText, { signal: controller.signal } );

// Function to change the content of t2
function modifyText() {
const t2 = document.getElementById("t2");
if (t2.firstChild.nodeValue == "three") {
t2.firstChild.nodeValue = "two";
} else {
t2.firstChild.nodeValue = "three";
controller.abort(); // remove listener after value reaches "three"
}
}

</pre>

<p>In the above example just above, we modify the code in the previous example such that after the second row’s content changes to "three", we call <code>abort()</code> from the {{domxref("AbortController")}} we passed to the <code>addEventListener()</code> call. That results in the value remaining as "three" forever — because we no longer have any code listening for a click event.</p>

<h4 id="Result">Result</h4>

<p>{{EmbedLiveSample('add_a_abortable_listener')}}</p>

<h3 id="Event_listener_with_anonymous_function">Event listener with anonymous function
</h3>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
and various optional options that may affect the matching process; see
{{anch("Matching event listeners for removal")}}</span></p>

<p>Note that event listeners can also be removed by passing an {{domxref("AbortSignal")}} to an {{domxref("EventTarget/addEventListener()", "addEventListener()")}} and then later calling {{domxref("AbortController/abort()", "abort()")}} on the controller owning the signal.</p>

<h2 id="Syntax">Syntax</h2>

<pre
Expand Down
2 changes: 1 addition & 1 deletion files/en-us/web/guide/events/event_handlers/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ <h2 id="Registering_onevent_handlers">Registering onevent handlers</h2>
<code>document.querySelector("button")<strong>.onclick = function(event) { … }</strong></code>.</li>
</ul>

<p>An <code>on<em>event</em></code>'s event handler property serves as a placeholder of sorts, to which a single event handler can be assigned. In order to allow multiple handlers to be installed for the same event on a given object, you can call its {{domxref("EventTarget.addEventListener", "addEventListener()")}} method, which manages a list of handlers for the given event on the object. A handler can then be removed from the object by calling its {{domxref("EventTarget.removeEventListener", "removeEventListener()")}} function.</p>
<p>An <code>on<em>event</em></code>'s event handler property serves as a placeholder of sorts, to which a single event handler can be assigned. In order to allow multiple handlers to be installed for the same event on a given object, you can call its {{domxref("EventTarget.addEventListener", "addEventListener()")}} method, which manages a list of handlers for the given event on the object. A handler can then be removed from the object either by calling its {{domxref("EventTarget.removeEventListener", "removeEventListener()")}} function, or else, if an {{domxref("AbortSignal")}} was passed to the {{domxref("EventTarget/addEventListener()", "addEventListener()")}} which set the handler, calling {{domxref("AbortController/abort()", "abort()")}} on the controller owning the signal.</p>

<p>When an event occurs that applies to an element, each of its event handlers is called to allow them to handle the event, one after another. You don't need to call them yourself, although you can do so in many cases to easily simulate an event taking place. For example, given a button object <code>myButton</code>, you can do <code>myButton.onclick(myEventObject)</code> to call the event handler directly. If the event handler doesn't access any data from the event object, you can leave out the event when calling <code>onclick()</code>.</p>

Expand Down

0 comments on commit 93fef08

Please sign in to comment.