Home > Enterprise >  UI change events being blocked
UI change events being blocked

Time:12-18

I have two elements, a paragraph and a button. On clicking the button, the browser should render the text "Waiting" with the p tag, wait 3 seconds and render the text "Done" after. It runs but the text "Waiting" is never rendered.

I know this can be solved with setTimeout but I am trying to understand why the text "Waiting" does not show up at all.

html:

<p id="p">Ready</p>
<button id="button">Start</button>

Javascript:

const pTag = document.getElementById('p');
const button = document.getElementById('button');


button.onclick = () => {
  pTag.innerText = 'Waiting';
  
  syncWaitSeconds(3)

  pTag.innerText = 'Done';
};

function syncWaitSeconds(seconds = 3){
  const start = Date.now();
  
  const time = seconds * 1000
  
  while (Date.now() - start <= time) {
    // waiting 3 seconds
  }
}

I am learning Javascript, I want to know why the text was not showing up. As changing the innerText does not return a promise and is synchronous, shouldn't it have happened first, then the wait for 3 seconds and finally the render of the text 'Done' ?

CodePudding user response:

It's because you are doing busy-wait, that is, your browser is too busy always comparing those dates and it simply does not get to update the UI. This is a good example for the need of asynchronity. It is not "just" the innerText that's not refreshing, it's the whole UI being unresponsive while this busy-wait happens.

This is why you need to do this asynchronously via setTimeout. Without setTimeout:

const pTag = document.getElementById('p');
const button = document.getElementById('button');


button.onclick = () => {
  pTag.innerText = 'Waiting';
  
  syncWaitSeconds(3)

  pTag.innerText = 'Done';
};

function syncWaitSeconds(seconds = 3){
  const start = Date.now();
  
  const time = seconds * 1000
  
  while (Date.now() - start <= time) {
    // waiting 3 seconds
  }
}
<p id="p"></p>
<button id="button">My Button</button>

With setTimeout:

const pTag = document.getElementById('p');
const button = document.getElementById('button');


button.onclick = () => {
  pTag.innerText = 'Waiting';
  
  setTimeout(function() {
      pTag.innerText = 'Done';
  }, 3000);

};
<p id="p"></p>
<button id="button">My Button</button>

  • Related