Skip to content

Commit 7a52b3e

Browse files
authored
Add examples for queueMicrotask()
Also rearranges the domintro and normative definition to come first, before the explanatory text.
1 parent 9d7cf12 commit 7a52b3e

File tree

1 file changed

+101
-11
lines changed

1 file changed

+101
-11
lines changed

source

Lines changed: 101 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2805,6 +2805,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
28052805
<li><dfn data-x="concept-fetch-terminate" data-x-href="https://fetch.spec.whatwg.org/#concept-fetch-terminate">terminate</dfn></li>
28062806
<li>the <dfn data-x-href="https://fetch.spec.whatwg.org/#requestcredentials"><code>RequestCredentials</code></dfn> enumeration</li>
28072807
<li>the <dfn data-x-href="https://fetch.spec.whatwg.org/#requestdestination"><code>RequestDestination</code></dfn> enumeration</li>
2808+
<li>the <dfn data-x-href="https://fetch.spec.whatwg.org/#dom-global-fetch"><code>fetch()</code></dfn> method</li>
28082809
<li>
28092810
<dfn data-x="concept-response"
28102811
data-x-href="https://fetch.spec.whatwg.org/#concept-response">response</dfn> and its
@@ -91365,6 +91366,19 @@ scheduleWork(); // queues a task to do lots of work</code></pre>
9136591366

9136691367
<h3>Microtask queuing</h3>
9136791368

91369+
<dl class="domintro">
91370+
<dt><var>self</var> . <code subdfn
91371+
data-x="dom-queueMicrotask">queueMicrotask</code>(<var>callback</var>)</dt>
91372+
<dd><p><span data-x="queue a microtask">Queues</span> a <span>microtask</span> to run the given
91373+
<var>callback</var>.</p></dd>
91374+
</dl>
91375+
91376+
<p w-nodev>The <dfn><code
91377+
data-x="dom-queueMicrotask">queueMicrotask(<var>callback</var>)</code></dfn> method must
91378+
<span>queue a microtask</span> to <span data-x="es-invoking-callback-functions">invoke</span>
91379+
<var>callback</var>, and if <var>callback</var> throws an exception, <span>report the
91380+
exception</span>.</p>
91381+
9136891382
<p>The <code data-x="dom-queueMicrotask">queueMicrotask()</code> method allows authors to schedule
9136991383
a callback on the <span>microtask queue</span>. This allows their code to run after the
9137091384
currently-executing <span data-x="concept-task">task</span> has run to completion and the
@@ -91380,18 +91394,94 @@ scheduleWork(); // queues a task to do lots of work</code></pre>
9138091394
before the next rendering cycle, that is the purpose of <code
9138191395
data-x="dom-window-requestAnimationFrame">requestAnimationFrame()</code>.</p>
9138291396

91383-
<dl class="domintro">
91384-
<dt><var>self</var> . <code subdfn
91385-
data-x="dom-queueMicrotask">queueMicrotask</code>(<var>callback</var>)</dt>
91386-
<dd><p><span data-x="queue a microtask">Queues</span> a <span>microtask</span> to run the given
91387-
<var>callback</var>.</p></dd>
91388-
</dl>
91397+
<p>As can be seen from the following examples, the best way of thinking about <code
91398+
data-x="dom-queueMicrotask">queueMicrotask()</code> is as a mechanism for rearranging synchronous
91399+
code, effectively placing the queued code immediately after the current task's worth of non-queued
91400+
JavaScript.</p>
9138991401

91390-
<p w-nodev>The <dfn><code
91391-
data-x="dom-queueMicrotask">queueMicrotask(<var>callback</var>)</code></dfn> method must
91392-
<span>queue a microtask</span> to <span data-x="es-invoking-callback-functions">invoke</span>
91393-
<var>callback</var>, and if <var>callback</var> throws an exception, <span>report the
91394-
exception</span>.</p>
91402+
<div class="example">
91403+
<p>The most common reason for using <code data-x="dom-queueMicrotask">queueMicrotask()</code> is
91404+
to create consistent ordering, even in the cases where information is available synchronously,
91405+
without introducing undue delay.</p>
91406+
91407+
<p>For example, consider a custom element firing a <code data-x="">load</code> event, that also
91408+
maintains an internal cache of previously-loaded data. A na&iuml;ve implementation might look
91409+
like:</p>
91410+
91411+
<pre><code class="js" data-x="">MyElement.prototype.loadData = function (url) {
91412+
if (this._cache[url]) {
91413+
this._setData(this._cache[url]);
91414+
this.dispatchEvent(new Event("load"));
91415+
} else {
91416+
fetch(url).then(res => res.arrayBuffer()).then(data => {
91417+
this._cache[url] = data;
91418+
this._setData(data);
91419+
this.dispatchEvent(new Event("load"));
91420+
});
91421+
}
91422+
};</code></pre>
91423+
91424+
<p>This na&iuml;ve implementation is problematic, however, in that it causes its users to
91425+
experience inconsistent behavior. For example, code such as</p>
91426+
91427+
<pre><code class="js" data-x="">element.addEventListener("load", () => console.log("loaded"));
91428+
console.log("1");
91429+
element.loadData();
91430+
console.log("2");</code></pre>
91431+
91432+
<p>will sometimes log "1, 2, loaded" (if the data needs to be fetched), and sometimes log "1,
91433+
loaded, 2" (if the data is already cached). Similarly, after the call to <code
91434+
data-x="">loadData()</code>, it will be inconsistent whether or not the data is set on the
91435+
element.</p>
91436+
91437+
<p>To get a consistent ordering, <code data-x="dom-queueMicrotask">queueMicrotask()</code> can be
91438+
used:</p>
91439+
91440+
<pre><code class="js" data-x="">MyElement.prototype.loadData = function (url) {
91441+
if (this._cache[url]) {<strong>
91442+
queueMicrotask(() => {
91443+
this._setData(this._cache[url]);
91444+
this.dispatchEvent(new Event("load"));
91445+
});</strong>
91446+
} else {
91447+
fetch(url).then(res => res.arrayBuffer()).then(data => {
91448+
this._cache[url] = data;
91449+
this._setData(data);
91450+
this.dispatchEvent(new Event("load"));
91451+
});
91452+
}
91453+
};</code></pre>
91454+
91455+
<p>By essentially rearranging the queued code to be after the currently-executing task, this
91456+
ensures a consistent ordering and update of the element's state.</p>
91457+
</div>
91458+
91459+
<div class="example">
91460+
<p>Another interesting use of <code data-x="dom-queueMicrotask">queueMicrotask()</code> is to
91461+
allow uncoordinated "batching" of work by multiple callers. For example, consider a library
91462+
function that wants to send data somewhere as soon as possible, but doesn't want to make multiple
91463+
network requests if doing so is easily avoidable. One way to balance this would be like so:</p>
91464+
91465+
<pre><code class="js" data-x="">const queuedToSend = [];
91466+
91467+
function sendData(data) {
91468+
queuedToSend.push(data);
91469+
91470+
if (queuedToSend.length === 1) {
91471+
queueMicrotask(() => {
91472+
const stringToSend = JSON.stringify(queuedToSend);
91473+
queuedToSend.length = 0;
91474+
91475+
fetch("/endpoint", string);
91476+
});
91477+
}
91478+
}</code></pre>
91479+
91480+
<p>With this architecture, multiple subsequent calls to <code data-x="">sendData()</code> within
91481+
the same turn of the event loop will be batched together into one <code>fetch()</code> call, but
91482+
with no intervening event loop tasks preempting the fetch (as would have happened with similar
91483+
code that instead used <code data-x="dom-setTimeout">setTimeout()</code>).</p>
91484+
</div>
9139591485

9139691486

9139791487
<h3>User prompts</h3>

0 commit comments

Comments
 (0)