Search code examples
javascriptdomrace-conditionflow-control

DOM Manipulation not executing in sequence


Looking for a solution or even just some "under the hood" theory behind what's going on in the following examples I put together.

It appears that manipulation of the DOM happens in a non-blocking fashion. In other words, there is no flow-control to wait for the execution of DOM statements.

In this example: http://jsfiddle.net/qHVJX/

Two statements are executed after an onclick event.

  1. shift text left to right

    document.getElementById('text').className = 'tr';
    
  2. loop a bunch of time to halt execution.

    for(var i = 0,temp=1000000000; i<temp;i++){var dummy=0;} 
    

If flow-control was blocked while each statement executed then, as expected, the text would shift left to right followed by a short pause from the loop. Instead, the text shift happens after the loop iterates.

This suggests that the className statement gets queued while the loop takes execution priority.

In this example: http://jsfiddle.net/qHVJX/1/

Three statements are executed after an onclick event:

  1. shift text left to right

    document.getElementById('text').className = 'tr';
    
  2. loop a bunch of time to halt execution.

    for(var i = 0,temp=1000000000; i<temp;i++){var dummy=0;}
    
  3. shift text right to left.

    document.getElementById('text').className = 'tl';
    

Again, If flow control was blocked while each statement executed then, as expected, the text would shift left to right followed by a short pause while the loop iterated, followed by the text shifting from right back to left.

Instead, the loop is executed and the repaint of the text from left to right and right to left never occurs. This illustrates a race condition.

setTimeout() could halt execution long enough for the DOM statement to do it's thing and avoid being queued, however; there is no way to know how long each statement is going to take. if the interval is set to short than it wont achieve the desired results. If the interval is set to be longer than it needs to be then performance suffers.

Is there anyway to block execution during DOM manipulation without the overhead of setTimeout()? Some sort of callback routine perhaps?

Any insight would be much appreciated. Thanks.


Solution

  • Not sure what you mean by "the overhead of setTimeout()", but calling setTimeout with the timeout of 0 seems to be the commonly suggested way of doing this.

    http://javascript.info/tutorial/events-and-timing-depth#the-settimeout-func-0-trick