Here is what will happen in the JavaScript execution environment:
document.body.style.backgroundColor
will change its value to 'green'
.
- A long-running process will run.
document.body.style.backgroundColor
will change its value to 'red'
.
It is unspecified how the changes in the backgroundColor
property will affect the appearance of the page, if the JavaScript thread is blocked.
Here's an example. If you click the word hello
, you will see a slight delay, and then the background will turn red:
function handleEvent(e){
document.body.style.backgroundColor = 'green';
longRunningFunction();
document.body.style.backgroundColor = 'red';
}
function longRunningFunction() {
for(var i=0; i<2000000000; ++i) { +i; }
}
document.body.addEventListener("click", handleEvent);
<div>hello</div>
This is because the browser's rendering engine that redraws in response to changes to CSS properties is blocked by the long-running blocking JavaScript function. This is not specified behavior, but rather an implementation reality for all browsers. See How can I force the browser to redraw while my script is doing some heavy processing? for a similar question.
I think any given browser could choose to run a separate redraw thread concurrent with the JavaScript thread, but I don't believe any major browsers currently do so. There may be race-condition complexities inherent in such an approach; I've never written a browser so I don't know.
If you want to show intermediate state, you can use a very quick setTiemout
call after setting backgroundColor
to green, to clear the JavaScript function stack and allow the renderer to redraw the page:
function handleEvent(e){
document.body.style.backgroundColor = 'green';
setTimeout(function() {
longRunningFunction();
document.body.style.backgroundColor = 'red';
}, 4);
}
This queues up the longRunningFunction
and second color change to run in 4 milliseconds in the future. During that idle 4 milliseconds, the renderer has chance to redraw the page.