2014-12-02 36 views
0

我在遇到以下問題。我已經構建了一個包裝函數,該函數顯示加載進度條並在執行函數後使其消失。現在它不顯示進度條,除非我在執行函數foo時設置斷點。DOM只在調試時更新

我在運行onload事件時取得了一些成功,但是它沒有執行endLoading。

function sleep(milliseconds) { 
    var start = new Date().getTime(); 
    for (var i = 0; i < 1e7; i++) if ((new Date().getTime() - start) > milliseconds) break; 
} 

var progress = document.createElement('progress'); 
var fillElement = document.body; 

function foo() { 
    console.log('foo start'); 
    sleep(2000); 
    fillElement.innerHTML = 'Bar'; 
    console.log('foo end'); } 

function startLoading() { 
    console.log('start'); 
    fillElement.innerHTML = ''; 
    fillElement.appendChild(progress);  
} 

function endLoading() { 
    console.log('end'); 
    fillElement.removeChild(progress); 
} 

startLoading(); 
foo(); // if the debug point is set here i can see the progress bar 
endLoading(); 
+1

使用['setTimeout'](https://developer.mozilla.org/en-US/Add-ons/Code_snippets/Timers)而不是忙碌循環。 – 2014-12-02 14:39:45

+1

瀏覽器是單線程的,事情會在發生任何事情之前完成。這意味着在DOM完成之前,DOM重繪不會發生。有一個斷點允許腳本暫停,並且瀏覽器將使用時間進行重繪,以反映javascript在DOM中創建的目前狀態。 – 2014-12-02 14:41:33

+1

你不能用JavaScript進行睡眠。壞的想法...那for循環不允許DOM更新。 – epascarello 2014-12-02 14:42:08

回答

0
function foo() { 
    console.log('foo start'); 
    setTimeout(function() { 
    fillElement.innerHTML = 'Bar'; 
    console.log('foo end'); 
    }, 2000); 
} 

應該做的

function foo() { 
    console.log('foo start'); 
    sleep(2000); 
    fillElement.innerHTML = 'Bar'; 
    console.log('foo end'); } 

相當於你可以連續使用操作

startLoading(chain(foo, endLoading)); 

function chain(x, y) { 
    return function() { x(y); } 
} 

function foo(afterwards) { 
    console.log('foo start'); 
    setTimeout(
    function() { 
     fillElement.innerHTML = 'Bar'; 
     console.log('foo end'); 
     afterwards(); 
    }, 
    2000); 
} 

,做一個類似的延續傳遞上startLoading變換。你也可以看看可以簡化這種編碼風格的期貨。