Skip to content

Commit

Permalink
Define AbortController and AbortSignal classes
Browse files Browse the repository at this point in the history
New APIs for a generic reusable abort mechanism.

Tests: ...

Fixes part of whatwg#438.

(This commit was also authored by Jake and Anne.)
  • Loading branch information
mikewest authored and annevk committed May 17, 2017
1 parent b2f4292 commit 7ee917d
Showing 1 changed file with 149 additions and 2 deletions.
151 changes: 149 additions & 2 deletions dom.bs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ No Editor: true
!Tests: <a href=https://github.com/w3c/web-platform-tests/tree/master/dom>web-platform-tests dom/</a> (<a href=https://github.com/w3c/web-platform-tests/labels/dom>ongoing work</a>)
!Translation (non-normative): <span title=Japanese><a href=https://triple-underscore.github.io/DOM4-ja.html lang=ja hreflang=ja rel=alternate>日本語</a></span>
Logo: https://resources.whatwg.org/logo-dom.svg
Abstract: DOM defines a platform-neutral model for events and node trees.
Abstract: DOM defines a platform-neutral model for events, aborting activities, and node trees.
Ignored Terms: EmptyString, Array, Document
Boilerplate: omit feedback-header, omit conformance
</pre>
Expand Down Expand Up @@ -557,7 +557,7 @@ algorithm below.
the operation that caused <var>event</var> to be <a>dispatched</a> that it needs to be canceled.

<dt><code><var>event</var> . {{Event/defaultPrevented}}</code>
<dd>Returns true if {{Event/preventDefault()}} was invoked successfully to indicate cancellation,
<dd>Returns true if {{Event/preventDefault()}} was invoked successfully to indicate cancelation,
and false otherwise.

<dt><code><var>event</var> . {{Event/composed}}</code>
Expand Down Expand Up @@ -1413,6 +1413,152 @@ can only be used to influence an ongoing one.



<h2 id=aborting-ongoing-activities>Aborting ongoing activities</h3>

<p>Though promises do not have a built-in aborting mechanism, many APIs using them require abort
semantics. {{AbortController}} is meant to support these requirements by providing an
{{AbortController/abort()}} method that toggles the state of a corresponding {{AbortSignal}} object.
The API which wishes to support aborting can accept an {{AbortSignal}} object, and use its state to
determine how to proceed.

<p>APIs that rely upon {{AbortController}} are encouraged to respond to {{AbortController/abort()}}
by rejecting any unsettled promise with a new {{DOMException}} with [=error name=] "{{AbortError}}".

<div class=example id=aborting-ongoing-activities-example>
<p>A hypothetical <code>doAmazingness({ ... })</code> method could accept an {{AbortSignal}} object
in order to support aborting as follows:

<pre><code class=lang-javascript>
const controller = new AbortController();
const signal = controller.signal;

startSpinner();

doAmazingness({ ..., signal })
.then(result => ...)
.catch(err => {
if (err.name == 'AbortError') return;
showUserErrorMessage();
})
.then(() => stopSpinner());

// &hellip;

controller.abort();</code></pre>

<p><code>doAmazingness</code> could be implemented as follows:

<pre><code class=lang-javascript>
function doAmazingness({signal}) {
return new Promise((resolve, reject) => {
// Begin doing amazingness, and call resolve(result) when done.
// But also, watch for signals:
signal.addEventListener('abort', () => {
// Stop doing amazingness, and:
reject(new DOMException('Aborted', 'AbortError'));
});
});
}
</code></pre>

<p>APIs that require more granular control could extend both {{AbortController}} and
{{AbortSignal}} objects according to their needs.
</div>


<h3 id=interface-abortcontroller>Interface {{AbortController}}</h3>

<pre class="idl">
[Constructor,
Exposed=(Window,Worker)]
interface AbortController {
[SameObject] readonly attribute AbortSignal signal;

void abort();
};</pre>

<dl class=domintro>
<dt><code><var>controller</var> = new <a constructor lt="AbortController()">AbortController</a>()</code>
<dd>Returns a new <var>controller</var> whose {{AbortController/signal}} is set to a newly
created {{AbortSignal}} object.

<dt><code><var>controller</var> . </code>{{AbortController/signal}}
<dd>Returns the {{AbortSignal}} object associated with this object.

<dt><code><var>controller</var> . </code>{{AbortController/abort()}}
<dd>Invoking this method will set this object's {{AbortSignal}}'s [=AbortSignal/aborted flag=],
thereby signaling to any observers that the associated activity should be aborted.
</dl>

<p>An {{AbortController}} object has an associated <dfn for=AbortController>signal</dfn> (an
{{AbortSignal}} object). When an {{AbortController}} object is created, its
<a for=AbortController>signal</a> must be set to a new {{AbortSignal}} object.

<p>The <dfn attribute for=AbortController><code>signal</code></dfn> attribute's getter must return
<a>context object</a>'s <a for=AbortController>signal</a>.

<p>The <dfn method for=AbortController><code>abort()</code></dfn> method, when invoked, must
<a for=AbortSignal>signal abort</a> on <a>context object</a>'s <a for=AbortController>signal</a>.


<h3 id=interface-AbortSignal>Interface {{AbortSignal}}</h3>

<pre class="idl">
[Exposed=(Window,Worker)]
interface AbortSignal : EventTarget {
readonly attribute boolean aborted;

attribute EventHandler onabort;
};</pre>

<dl class=domintro>
<dt><code><var>signal</var> . </code>{{AbortSignal/aborted}}
<dd>Returns true if this {{AbortSignal}} has been aborted, and false otherwise.
</dl>

<p>An {{AbortSignal}} object has an associated <dfn for=AbortSignal>aborted flag</dfn>. It is unset
unless specified otherwise.

<p>An {{AbortSignal}} object has associated <dfn for=AbortSignal>abort algorithms</dfn>, which is a
<a for=/>set</a> of algorithms which are to be executed when its [=AbortSignal/aborted flag=] is
set. Unless specified otherwise, its value is the empty set.

<p class="note no-backref">The [=AbortSignal/abort algorithms=] enable APIs with complex
requirements to react in a reasonable way to {{AbortController/abort()}}. For example, a given API's
[=AbortSignal/aborted flag=] might need to be propagated to a cross-thread environment, such as a
service worker.

<p>The <dfn attribute for=AbortSignal>aborted</dfn> attribute's getter must return true if
<a>context object</a>'s [=AbortSignal/aborted flag=] is set, and false otherwise.

<p class=note>Changes to an {{AbortSignal}} object represent the wishes of the corresponding
{{AbortController}} object, but an API observing the {{AbortSignal}} object can chose to ignore
them. For instance, if the operation has already completed.

<p>To <dfn export for=AbortSignal>signal abort</dfn>, given a {{AbortSignal}} object
<var>signal</var>, run these steps:

<ol>
<li><p>If <var>signal</var>'s [=AbortSignal/aborted flag=] is set, then return.

<li><p>Set <var>signal</var>'s [=AbortSignal/aborted flag=].

<li><p><a for=set>For each</a> <var>algorithm</var> in <var>signal</var>'s
[=AbortSignal/abort algorithms=]: run <var>algorithm</var>.

<li><p>[=Fire an event=] named <code event for=AbortSignal>abort</code> at <var>signal</var>.
</ol>


<h3 id=abortcontroller-api-integration>Using {{AbortController}} and {{AbortSignal}} objects in
APIs</h3>

<p>Any web platform API using promises that to represent operations that can be aborted must accept
{{AbortSignal}} objects, use the [=AbortSignal/abort algorithms=] mechanism, and convey that the
operation got aborted by rejecting the promise with the "{{AbortError}}" {{DOMException}}.



<h2 id=nodes>Nodes</h2>

<h3 id=introduction-to-the-dom>Introduction to "The DOM"</h3>
Expand Down Expand Up @@ -9756,6 +9902,7 @@ Mounir Lamouri,
Michael™ Smith,
Mike Champion,
Mike Taylor,
Mike West,
Ojan Vafai,
Oliver Nightingale,
Olli Pettay,
Expand Down

0 comments on commit 7ee917d

Please sign in to comment.