最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Any example proving microtask is executed before rendering? - Stack Overflow

programmeradmin3浏览0评论

I saw several articles says that render steps are after microtasks.

I test it with this code:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <p>test</p>
  <script>
const p = document.querySelector('p');
p.textContent = 'text';
Promise.resolve().then(function microtask() {
  debugger;
  p.textContent = 'Promise';
});
  </script>
</body>
</html>

This code seems show that the UI is re-rendered before the microtask run.

Am i think about it wrong? Is there any good example shows that rendering is after microtask run ?

I saw several articles says that render steps are after microtasks.

I test it with this code:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <p>test</p>
  <script>
const p = document.querySelector('p');
p.textContent = 'text';
Promise.resolve().then(function microtask() {
  debugger;
  p.textContent = 'Promise';
});
  </script>
</body>
</html>

This code seems show that the UI is re-rendered before the microtask run.

Am i think about it wrong? Is there any good example shows that rendering is after microtask run ?

Share Improve this question asked Jun 24, 2020 at 19:38 js100ccjs100cc 575 bronze badges 5
  • It doesn't really matter when the DOM is rendered. That you cannot observe it is the whole point allowing browsers to defer it, not re-rendering after every single change. – Bergi Commented Jun 24, 2020 at 19:45
  • 1 Are you saying that the DOM is rendered when you pause code in a debugger? Or that it does not happen? – Bergi Commented Jun 24, 2020 at 19:46
  • The DOM is rendered when i pause code in debugger. My purpose is prove that p.textContent wouldn't be text before microtask run. – js100cc Commented Jun 24, 2020 at 20:16
  • 1 p.textContent = 'text'; does happen before any microtask is even scheduled? – Bergi Commented Jun 24, 2020 at 20:26
  • UI is blocked by JS before JS stack is cleaned up. – js100cc Commented Jun 24, 2020 at 20:40
Add a ment  | 

1 Answer 1

Reset to default 12

You can simply prove it by looking at the event-loop processing model. To paraphrase its current status while omitting the few steps we're not interested in:

    1. Choose a task to execute
    1. Execute that task
    1. Perform microtask end-point
    1. Update the rendering (if it's time to do so)
    1. Repeat

So here it's quite clear microtasks are executed before the rendering happens.

Not yet convinced?

Here is a snippet which will block your UI for 5s using only microtasks. The page content will not be rendered before this lock is released:

// We wrap our code in a 0 timeout and two rAF levels
// to be sure the initial rendering of the page did occur
setTimeout( () => {
requestAnimationFrame( () => {
  requestAnimationFrame( () => {

    // Now we modify the DOM
    document.querySelector( 'p' ).textContent = "modified";
    // and we start locking the UI using a Promise chain
    const start = performance.now();
    (function lockUI() {     // IIFE
      if( performance.now() - start  < 5000 ) {
        // recursive Promise chaining
        // all these promises will get executed before the next rendering
        // and block the UI rendering
        // even though we were in an rAF callback!
        return Promise.resolve()
          .then( lockUI );
      }
    } )();
    
  } );
} );
}, 0 );
<p>Initial (please wait 5s)</p>

The careful readers will notice that this script is not even queuing microtasks to the 7th step of the event loop, but to the 11.12 interleaved microtask checkpoint.

This only better cements the point that the actual rendering is only done at step 11.15, and that anything before can actually delay it.


So in your test case, "text" should never be rendered, since by calling Promise.resolve().then() you actually queue a microtask, which from the event-loop's point of view is actually the same as a synchronous operation here since there is nothing going on after that queuing.
Except that there is a case where you could still see the text rendered anyway, which is if the browser enters the spin the event loop algorithm. This may happen if the browser faces a long task and decides it can execute this algorithm, which will allow for the rendering steps to occur even though there is still a long task being ran.
For instance, Firefox does this whenever you initiate modals like alert() or prompt() etc.

So in Firefox, this snippet will actually render the text text, Chrome doesn't call this algorithm here, so it won't render anything, not even the initial test:

const p = document.querySelector('p');
p.textContent = 'text';
Promise.resolve().then(function microtask() {
  alert();
  p.textContent = 'Promise';
});
<p>test</p>

However Chrome does call this algorithm with debugger. So this keyword will not block the rendering, and that's why you do see text being rendered.

发布评论

评论列表(0)

  1. 暂无评论