Say I have the following javascript event handler:
function handleEvent(e){
document.body.style.backgroundColor = 'green';
longRunningFunction();
document.body.style.backgroundColor = 'red';
}
Will the browser first display a green background and then switch it to red? Or display the red background directly?
According to my testing it displays red directly at the end of the event handler. But is that part of the specification, or just incidental to how browsers happen to be implemented?
UPDATE:
I should clarify that I am not "aiming" for this effect. Rather, I want to have some guarantee that it does not happen. Some of my event handlers change many things, and it makes my life easier if I can assume that none of the intermediate states are rendered.
Here is what will happen in the JavaScript execution environment:
document.body.style.backgroundColor
will change its value to 'green'
.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With