title: How does the following queueMicrotask polyfill fallback to using setTimeout?
body: <p>Consider the following <a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/queueMicrotask#When_queueMicrotask_isnt_available" rel="noreferrer">polyfill</a> for <a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/queueMicrotask" rel="noreferrer"><code>queueMicrotask</code></a>.</p>
  
  <pre class="lang-js prettyprint-override"><code>if (typeof window.queueMicrotask !== "function") {
    window.queueMicrotask = function (callback) {
      Promise.resolve()
        .then(callback)
        .catch(e =&gt; setTimeout(() =&gt; { throw e; }));
    };
  }
  </code></pre>
  
  <p>The description on MDN states.</p>
  
  <blockquote>
    <p>It creates a microtask by using a promise that resolves immediately, falling back to using a timeout if the promise can't be created.</p>
  </blockquote>
  
  <p>The <a href="https://github.com/feross/queue-microtask" rel="noreferrer">queue-microtask</a> library also uses the same polyfill. Here's what its documentation says.</p>
  
  <blockquote>
    <ul>
    <li>Optimal performance in all modern environments.
    
    <ul>
    <li>Use <code>queueMicrotask</code> in modern environments (optimal)</li>
    <li>Fallback to <code>Promise.resolve().then(fn)</code> in Node.js 10 and earlier, and old browsers (optimal)</li>
    <li>Fallback to <code>setTimeout</code> in JS environments without Promise (slow)</li>
    </ul></li>
    </ul>
  </blockquote>
  
  <p>This raises more questions than answers.</p>
  
  <ul>
  <li>Wouldn't <code>Promise</code> be <code>undefined</code> in JS environments without promises?</li>
  <li>Why are we throwing the error instead of calling <code>callback</code> within <code>setTimeout</code>?</li>
  <li>Why are we using a separate <code>catch</code> instead of passing the error handler to <code>then</code>?</li>
  <li>How does this polyfill fallback to using <code>setTimeout</code> when &ldquo;the promise can't be created&rdquo;?</li>
  <li>When would the promise not be created?</li>
  </ul>
  
  <p>I would have expected the polyfill to be implemented as follows.</p>
  
  <pre class="lang-js prettyprint-override"><code>if (typeof window.queueMicrotask !== "function") {
    window.queueMicrotask = callback =&gt;
      typeof Promise === "function" &amp;&amp; typeof Promise.resolve === "function"
        ? Promise.resolve().then(callback)
        : setTimeout(callback, 0);
  }
  </code></pre>
  
  <p>What's the reason why it's not implemented so?</p>
  
  <p><strong>Edit:</strong> I was going through the commit history of the queue-microtask library and I found <a href="https://github.com/feross/queue-microtask/commit/3a34dc827c2915505c0286c70800284659a20898" rel="noreferrer">this commit</a>.</p>
  
  <pre class="lang-js prettyprint-override"><code>@@ -1,9 +1,8 @@
  -let resolvedPromise
  +let promise
  
   module.exports = typeof queueMicrotask === 'function'
     ? queueMicrotask
  -  : (typeof Promise === 'function' ? (resolvedPromise = Promise.resolve()) : false)
  -    ? cb =&gt; resolvedPromise
  -      .then(cb)
  -      .catch(err =&gt; setTimeout(() =&gt; { throw err }, 0))
  -    : cb =&gt; setTimeout(cb, 0)
  +  // reuse resolved promise, and allocate it lazily
  +  : cb =&gt; (promise || (promise = Promise.resolve()))
  +    .then(cb)
  +    .catch(err =&gt; setTimeout(() =&gt; { throw err }, 0))
  </code></pre>
  
  <p>So, it seems as though this library did indeed fallback to using <code>cb =&gt; setTimeout(cb, 0)</code>. However, this was later removed. It might have been a mistake which went unnoticed. As for the MDN article, they might have just copied the snippet blindly from this library.</p>