Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

JavaScript — DOM changes with alert

I have a while loop going with an alert() inside. Inside the while loop, I want to change the content of an element, in this case with a counter.

I have a snippet which shows the idea.

var test = document.querySelector('div#test');
var limit = 5;
var counter = 0;
do {
  counter++;
  test.textContent = counter;
  console.log(counter)
  alert('waiting …');
} while (counter<limit);
div#test {
  text-align: center;
}
<div id="test"></div>

For testing purposes, I also include a console.log() but in the snippet it’s not working like a normal console.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I know that alert() is very disruptive, and blocks other activity. However, I find that somehow it prevents the element content from being changed, even though that statement is before the alert() in the loop. However, the console.log() statement is working, even though you can’t see it in the SO snippet. On a browser, such as Firefox and Safari, the console.log() prints the new value, but the element content stays unchanged until the end.

I also want the change the CSS style of the element, but I’ve left that off the sample. In any case it doesn’t work either.

I’m curious about what seems to be inconsistent behaviour. What is happening here, and is there a way to allow changes to the element to occur when there’s an alert() going on?

>Solution :

Your code is sync meaning you change the counter inside 1 JS task without allowing the browser to re-render the page. The rendering happens in the end of a JS task. To allow the browser to render you should split your logic into JS tasks. setTimeout and requestAnimationFrame create a new JS task for example.

We have a problem with Firefox though. Seems it optimizes the rendering and if several JS tasks are queued, it re-renders after all the queue is complete. So I’ve added 10ms delay:

var test = document.querySelector('div#test');

const wait = () => new Promise(resolve => setTimeout(resolve, 10));

(async()=>{

  var limit = 5;
  var counter = 0;
  do {
    counter++;
    test.textContent = counter;
    console.log(counter);
    alert('waiting …');
    await wait();
  } while (counter<limit);

})();
div#test {
  text-align: center;
}
<div id="test"></div>

enter image description here

A simplified solution:

var test = document.querySelector('div#test');

var limit = 5;
var counter = 0;

const count = () => {
    counter++;
    test.textContent = counter;
    console.log(counter);
    alert('waiting …');
    counter<limit && setTimeout(count, 10);
};
count();
div#test {
  text-align: center;
}
<div id="test"></div>

We could also use requestAnimationFrame:

var test = document.querySelector('div#test');

var limit = 5;
var counter = 0;

const count = () => {
    counter++;
    test.textContent = counter;
    console.log(counter);
    alert('waiting …');
    counter<limit && requestAnimationFrame(count);
};
requestAnimationFrame(count)
div#test {
  text-align: center;
}
<div id="test"></div>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading