最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

html - If I make DOM changes in a Javascript event handler, are the changes rendered incrementally, or just once at the end? - S

programmeradmin2浏览0评论

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.

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.

Share Improve this question edited May 20, 2015 at 19:49 user2771609 asked May 20, 2015 at 19:16 user2771609user2771609 1,9031 gold badge15 silver badges39 bronze badges 2
  • i think there are some styles that will show up right away, if they affect layout. generally, dom stuff gets behind in a thread that does other stuff.a short timeout around the last two lines would make sure green shows first. – dandavis Commented May 20, 2015 at 19:19
  • 2 Javascript is single threaded so your longRunningFunction() will block. Whether or not a redraw might happen while you function is running, I certainly wouldn't rely on it. – Matt Burland Commented May 20, 2015 at 19:19
Add a ment  | 

2 Answers 2

Reset to default 11

Here is what will happen in the JavaScript execution environment:

  1. document.body.style.backgroundColor will change its value to 'green'.
  2. A long-running process will run.
  3. 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 plexities 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.

Does this illustrate what you're aiming for?

function handleEvent(e){
    document.body.style.backgroundColor = 'green';
    alert();
    document.body.style.backgroundColor = 'red';
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论