1

I have a heavy javascript job that prevents me from showing progress to the user. Is there any way to force refresh the window?

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

{
 var date = new Date();
 for (var i = 0; i< 238801000000000000; i++) {
  if (new Date() - date > 5000) {
   document.getElementById('iddds').innerHTML = 'FINISH';
   return;
  }
  if ((i % 10000) == 0) {
   var el = document.getElementById('iddds');
   el.innerHTML = i;
   redraw(el, document.getElementById('parent'));
   
   console.log(i);
  }
 }
});

function redraw(element, e3lement) {
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<div id='parent'>
 <span id='iddds'>Hello world!!!!!!!!!!!!!</span>
</div>

<button>START</button>
</html>

I've tried all the answers given here: How can I force WebKit to redraw/repaint to propagate style changes? and Force DOM redraw/refresh on Chrome/Mac - and these didn't work, so I assume it is impossible, but given that there are many people who +'d the answers I thought maybe I'm doing something wrong?

  • My heavy job is DOM manipulation - Web Workers will not work here.
  • I could try to split the job with setTimeout's or something similar, but I do not really want to delay the job or make it slower just to be able to show the progress.
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
Archeg
  • 8,364
  • 7
  • 43
  • 90
  • 1
    Consider copying the part of dom you want to manipulate and do that manipulation in web worker then update dom with new structure – charlietfl May 28 '18 at 13:13
  • 1
    Two things that should help: 1) Stop scanning the DOM for element references every time you loop. Get them once before the loop begins. 2) Don't use `.innerHTML` when you aren't getting/setting HTML, use `.textContent` instead. – Scott Marcus May 28 '18 at 13:13
  • An occasional `setTimeout( ..., 0 )` should not make the task any slower, other than the time it takes to refresh the DOM. – JJJ May 28 '18 at 13:15
  • Wouldn't `setImmediate()` be more appropriate here? – Andrii Maletskyi May 28 '18 at 13:18
  • Please explain what the `redraw()` function does. What kind of updates are you making to the UI? This may be able to be done with CSS or `requestAnimationFrame()`. – Scott Marcus May 28 '18 at 13:18
  • @AndriyMaletsky What is `setImmediate()`? – Scott Marcus May 28 '18 at 13:20
  • wow, it seems that `setImmediate()` is not standard. My nodejs experience doesn't project well onto frontend, sorry then – Andrii Maletskyi May 28 '18 at 13:27
  • @ScottMarcus This is an artificial example, that I agree I wrote a bit stupidly. Your corrections are proper, unfortunately, do not really help with the problem – Archeg May 28 '18 at 13:30
  • @ScottMarcus `redraw()` is the empty function I wanted to fill with redraw mechanics. I'm coming from C# background so I hoped for something like `Application.DoEvents()` call. I see now there is no such thing – Archeg May 28 '18 at 13:32
  • Did you try working with webworkers or doing the calculation asynchronously? – obey May 28 '18 at 13:33

2 Answers2

2

Is there any way to force refresh the window?

During that single long-running for loop on the main UI thread? No, there isn't.

Instead, your choices are:

  1. Move that long-running process off the main UI thread into a web worker; have that worker post updates to the main thread, which it renders in the DOM.

  2. Break it up into smaller parts, and after each part use setTimeout to schedule the next part, so that the browser has a chance to refresh. The UI will remain blocked during each part, but can update in-between them. Beware that this can make the process take a lot longer in real time; a web worker is the way to go if at all possible.


(Also best to avoid constantly repeating getElementById when you can do it just once at the outset and reuse the reference you get back.)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • I actually had no idea you can do DOM from web worker, this sounds amazing and I definitely will be looking more into web workers, although I still have doubts I can do the thing I'm doing right now. My job is to plot many plots with millions of points with `plotly.js` and then produce a pdf out of it with `jsPDF`. But thanks, I can for sure count this as an answer - seems like `setTimeout` is the way to go then for now – Archeg May 28 '18 at 13:34
  • @Archeg - Web workers don't have access to the DOM. To update the DOM from the worker, you have to have the worker post a message to the main thread, which does the update. My answer to the [linked question](https://stackoverflow.com/questions/46346297/long-running-code-inside-html-javascript) has a complete example. Happy coding! – T.J. Crowder May 28 '18 at 13:37
  • Then it means I can't have Web Workers there as I thought. I have around 1 minute of plotting and generating pdf out of it. But I still need to look more into Web Workers I guess, for now. To be honest I do not really understand the web workers - it looks to me like their usage scenario is extremely limited – Archeg May 28 '18 at 13:42
  • @Archeg - Depending on the details of the plotting and PDF generation, it may be right up their alley -- or not at all, if it's DOM-heavy. – T.J. Crowder May 28 '18 at 13:46
-4

try to add your script in other file and then include it in your file using this below.

<script async src="{{url}}" type="text/javascript"></script>
sandeep kumar
  • 124
  • 1
  • 4