user8763613
user8763613

Reputation: 51

jquery, css not changes before long time exec function

function doact() {
  $('p.main').addClass("hide");
  $('p.loading').removeClass("hide");

  //this is only example of long time exec function
  for (var i = 0; i < 1000000000; i++) {
    for (var j = 0; j < 2; j++) {}
  }
  //

  $('p.loading').addClass("hide");
  $('p.main').removeClass("hide");

  alert('done');
}
.hide {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="loading hide">loading...</p>
<p class="main">bla bla bla</p>
<input id="btn" type="button" value="do action" onclick="doact()" />

When I click the button, loading... does not appear and main does not disappear, only done message. How can implement such an algorithm?

Upvotes: 2

Views: 47

Answers (1)

Rory McCrossan
Rory McCrossan

Reputation: 337627

The issue is because JS is single-threaded. Hence the renderer does not get enough time to re-paint the UI before it starts the huge loop. It then can only update after the loop completes, at which time it hides the element, then shows it again straight away, hence nothing appears to happen.

To fix this, run the blocking code in a setTimeout() with a slight delay which gives the UI time to update before starting the loop.

Also note that on* event attributes should be avoided. I've amended your code to use an unobtrusive JS handler, as you have included jQuery anyway:

$('#btn').click(function() {
  $('p.main, p.loading').toggleClass("hide");

  setTimeout(function() {
    for (var i = 0; i < 1000000000; i++) {
      for (var j = 0; j < 2; j++) {}
    }

    $('p.main, p.loading').toggleClass("hide");
    console.log('done');
  }, 50);
})
.hide {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<p class="loading hide">loading...</p>
<p class="main">bla bla bla</p>
<input id="btn" type="button" value="do action" />

With that said, long-running synchronous operations which block the UI are a very bad pattern. I'd strongly suggest refactoring your code so that you avoid this.

Upvotes: 3

Related Questions