0

Until all events are completed changes in html do not occur

(function(){
    function sleep(ms) {
        const date = Date.now();
        do {
        } while (Date.now() - date < ms);
    }
    let button = document.getElementById('update');
    
    //basic code example:
    /*button.addEventListener('click', event => {
        event.target.value = 'aaa';
        sleep(1000);//or another long process
        event.target.value = 'bbb';
    });/**/

    //even so:
    button.addEventListener('click', event => {
        event.target.value = 'aaa';
    });
    button.addEventListener('click', event => {
        sleep(1000);//or another long process
    });
    button.addEventListener('click', event => {
        event.target.value = 'bbb';
    });
})();
<input type="button" value="Update" name="update" id="update">

This applies to all types of events.

What is the reason for this?

Is there a way to change html during(before) the execution of event?

3
  • why are you adding multiple click listener on button element? Commented May 20, 2021 at 11:44
  • @RahulKumar To demonstrate the problem I would think Commented May 20, 2021 at 11:44
  • 2
    You need to execute the long-running code separately to the UI, asynchronously. I would suggest investigating Promise which is a common mechanism for achieving this Commented May 20, 2021 at 11:45

2 Answers 2

1

As Martin mentioned in the comments, you should read up on the Promise object, and asynchronous operations. see: Using Promises

Here is your snippet with the MDN example Promise.

(function () {
  function sleep(ms) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('done');
      }, ms);
    })
  }
  let button = document.getElementById('update');

  //basic code example:
  button.addEventListener('click', event => {
    sleep(2000).then(res => event.target.value = res);//or another long process
    event.target.value = 'loading...';
  });
})();
<input type="button" value="Update" name="update" id="update">

Sign up to request clarification or add additional context in comments.

Comments

0

Add the value change as callback to the long running function and use setTimeout to trigger a repaint:

document.addEventListener("click", bttnEx);

function bttnEx(evt) {
  const origin = evt.target;
  if (origin.name === "update") {
    origin.value = "waiting...";
    const longRun = () => sleep(2000, () => origin.value = "done!");
    return setTimeout(longRun, 1);
  }
}

function sleep(ms, callback) {
  const date = Date.now();
  do {} while (Date.now() - date < ms);
  callback();
}
<input type="button" value="Update" name="update" id="update">

You can also use requestAnimationFrame in a nested fashion:

document.addEventListener("click", bttnEx);

    function bttnEx(evt) {
      const origin = evt.target;
      
      if (origin.name === "update") {
        const runSomethingLongAndReEnable = () => {
          const date = Date.now();
          do {} while (Date.now() - date < 2000);
          origin.value = "Update";
          origin.disabled = false;
        };
        const waitAndDisable = () => {
          origin.value = "Busy...";
          origin.disabled = true;
          requestAnimationFrame(runSomethingLongAndReEnable);
        };
        
        return requestAnimationFrame(waitAndDisable);
      }
    }
body {
  margin: 2rem;
}
input[disabled] {
  color: red !important;
}
<input type="button" value="Update" name="update" id="update">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.