0

I have this code:

$( "#drawingSurface" ).mousedown(function(event) {
 $('.infoText').text('Started! Please Wait..');
 compilation(); // this takes a long time.
}

Now no matter what I do, $('.infoText').text('Started! Please Wait..'); will just not execute. The element is there, it is annoying because compilation takes ages to finish and when it is done then the text shows up. I want the text to SHOW up as in the order that I have written things.

Huangism
  • 16,278
  • 7
  • 48
  • 74
Trt Trt
  • 5,330
  • 13
  • 53
  • 86

3 Answers3

2

It's executing, but while compilation is running, it prevents the browser from updating the display of the page.

You can fix that by introducing a very brief delay between the text update and compilation:

$( "#drawingSurface" ).mousedown(function(event) {
    $('.infoText').text('Started! Please Wait..');
    setTimeout(compilation, 50);
});

That way the browser has a chance to show the change before blocking on the long-running compilation. (0 usually works on Chrome, but Firefox typically needs about 50. YMMV.)

If you can, consider moving compilation to a web worker (spec | MDN) so you don't have to block the main UI thread at all.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • still not working... I added $('.infoText').text('started! Please Wait..'); setTimeout(compilation(foo), 150); – Trt Trt Mar 12 '18 at 21:17
  • @TrtTrt: That still [calls `compilation` right away](https://stackoverflow.com/questions/27643714/settimeout-calls-function-immediately-instead-of-after-delay), and then passes its return value into `setTimeout`, exactly like `foo(bar())` *calls* `bar` and passes its return value into `foo`. If you need to pass `foo` to `compilation`, then: `setTimeout(function() { compilation(foo); }, 50)` or `setTimeout(compilation.bind(null, foo))`. – T.J. Crowder Mar 13 '18 at 07:24
0

Seems like the DOM update does not behave synchronously (edit: not exactly, see comments), so it begins executing your function (compilation()) before the text in the div changes. As a workaround, you could add it to a timeout such as the following

$( () => {
  $( "#drawingSurface" ).mousedown(function(event) {
   console.log('hi');
   $('.infoText').text('Started! Please Wait..');
    setTimeout(doWork, 1);
  });
});



function doWork() {
 let i = 0;
  while (i < 1e3) {
   console.log('waiting');
    i++
  }
  $('.infoText').text('Done.');
  console.log('finished');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="drawingSurface">
  Click me
</div>

<div class="infoText">
text
</div>
  • *"Seems like the DOM update does not behave synchronously, so it begins executing your function (compilation()) before the text in the div changes."* The DOM update is synchronous. The *rendering* of that update is not, and is what's heled up by `compilation`. See my answer. – T.J. Crowder Mar 12 '18 at 17:25
  • I see, so it is due to how the browser handles the change of the DOM that causes the delay? On a side note, I also noticed that when the doWork() function took a very long time, the text actually updated before the function completed (although it took several seconds for the change to appear). – Hugh Percival Mar 12 '18 at 17:29
  • Yes, but they've mostly converged on the same model for it, not least for `requestAnimationFrame` support: The rendering is done on the same thread JavaScript runs on, between JavaScript tasks, up to 60 times/second. – T.J. Crowder Mar 12 '18 at 17:31
-1

Alternatively, you could move '$('.infoText').text('Started! Please Wait..');' to be inside the compilation function.

Paul Bitner
  • 13
  • 1
  • 4