I'm working in Angular 2, trying to show a loader before a heavy computation and hiding it afterward. When I show the loader, the DOM is updating, but the view is not repainting. Therefore, my loader never appears.
Full code is here.
How is this possible?
The issue was that my browser was freezing from the heavy computation. The browser didn't have a chance to repaint after I showed the loader, because when it tried to repaint, the heavy computation was blocking the stack.
In other words, we want to ensure the loader reveal goes on the stack BEFORE the heavy computation (I will call this function "H") goes on the stack, so that "H" doesn't block the stack while the browser tries to repaint.
I figured out the solution by watching a brilliant video about asynchronicity / event loops / task queues / etc.
The solution is:
<loader-show>
setTimeout(() => {
<heavy-computation>
<loader-hide>
}, 20)
wrap both "H" and the loader hide inside a setTimeout
. This way, the loader reveal will go on the stack, then "H" and loader hiding will go to the task queue, and will only be pushed onto the stack (executed) when the stack is empty (ie. after loader reveal).
BUT notice the "20" ms delay in setTimeout
? Another critical element from the video is that
the browser repaints every 16 milliseconds
meaning that my setTimeout
has to delay by >16 seconds in order to ensure that the browser will repaint the view before "H" executes and blocks the stack.
Here is the solved code.