0

I've been reading about the single-thread nature of javascript and how the UI will not update until the code is complete (eg. this question). The responses to that question mainly explained how the code executes, but didn't provide a real viable solution outside of some "hacky" timers.

I'm wondering if there is a good solution, that may include promises, or .then() functionality that will "paint" the UI prior to javascript execution.

The following is a specific example: http://jsfiddle.net/zbtsd12k/. In this example I would expect the "Change Color" to change immediately, prior to the calculation being run.

WARNING: My example includes a for-loop of one billion iterations (which took < 2 seconds on my machine) and may freeze your computer for a bit.

Any help would be appreciated.

elPastor
  • 8,435
  • 11
  • 53
  • 81
  • 3
    is it just me who finds this question unclear? – treyBake Jan 02 '19 at 17:13
  • @treyBake - did you try the example? It should be pretty obvious what I'm asking. – elPastor Jan 02 '19 at 17:14
  • I did .... it just didn't make sense | edit: wait are you asking, change colour should run before the calculations even start? – treyBake Jan 02 '19 at 17:14
  • @treyBake - yes. Color should change immediately, then the calculations run. Which is what I wrote in my original question. – elPastor Jan 02 '19 at 17:15
  • Why not do an AJAX (**asynchronous** JavaScript and XML) request then? o.O – treyBake Jan 02 '19 at 17:15
  • 2
    You can allow the dom the chance to update by putting your logic in a setTimeout with a low timeout threshold – Taplar Jan 02 '19 at 17:17
  • @treyBake - I'm not familiar with AJAX requests that aren't meant for GET or POST functions. If you want to update my JSFiddle and post an answer, I'll accept it if it gets the job done. – elPastor Jan 02 '19 at 17:22
  • @Taplar - great idea, and very succinct. – elPastor Jan 02 '19 at 17:22
  • @elPastor it can be and I think the primary use is for updates without refresh. However, it may be utilised to be used for things like this - I could be wrong, I'm no AJAX/JS expert, but AJAX was the first thing that came to mind after realising the question – treyBake Jan 02 '19 at 17:23
  • @elPastor https://jsfiddle.net/zbtsd12k/3/ <-- it errors in console, but if you make a normal page and open in browser it works – treyBake Jan 02 '19 at 17:29
  • I don't understand the creation of an ajax request, *just* to detach the logic from the main thread execution. That's major overkill – Taplar Jan 02 '19 at 17:30
  • @treyBake - that's it. I'm surprised the `url` param needs to be there, but I tried it without and it fails. Thank you! – elPastor Jan 02 '19 at 17:30
  • @elPastor I don't know if it does (you can experiment) but glad it helps :) – treyBake Jan 02 '19 at 17:32

1 Answers1

5

A few changes

  • Added a setTimeout around the "logic" so that the DOM has a chance to redraw
  • Broke apart the then(makeCalculations()) line because #1 updateClass() does not return a promise and #2 then(methodCall()) would execute the methodCall immediately because you put () on the end of it.

function updateClass(element, newClass) {
  element.addClass(newClass);
  return true;
};

function makeCalculations() {
  $("p").text("Running...");

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

    $("p").html("Done!" + "<br />" + "x = " + x);
  }, 10);
}

$(function() {

  $("button").click(function() {

    updateClass($("span"), "purple");
    makeCalculations();

  });

});
.purple {
  color: purple;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span>Change Color</span>
<br>
<button>Click Me</button>
<p>Click the button</p>
Taplar
  • 24,788
  • 4
  • 22
  • 35