2012-08-22 31 views
3

我有一個網頁,顯示一個包含大量數據的圖表。該圖表是第三方Flash組件。JS中的網站加載結構

很多數據都是在加載初始頁面之後,在AJAX中延遲加載並輸入到圖表中的。我的問題是,雖然發生這種情況,頁面凍結多次,直到所有的數據加載。這是一個問題,尤其是因爲頁面加載,並且似乎所有內容都已準備就緒,但隨後在使用AJAX加載數據時,頁面會凍結。 一個很好的例子是setInterval我有每1秒遞增一個時鐘。此時鐘在AJAX加載過程中視覺凍結。

這怎麼可以避免?你會推薦一個不同的加載結構嗎?

+2

你能分享一些代碼? AJAX調用不應該阻止頁面,除非它不是異步的。 –

+2

嗨,你可以加載頁面加載時的ajax數據。讓我們說,當頁面加載時,您可以在頁面中獲取json數據作爲javascript變量,並將該數據添加到您的Flash代碼中。簡而言之,您可以預先加載數據並以json格式存儲,而不是使用ajax調用。 –

+1

我猜凍結髮生的原因是因爲很多數據被加載到Flash中,而不是因爲實際的AJAX請求... – user1094786

回答

2

你的問題其實很簡單,雖然解決方案有點棘手。您遇到「凍結」的原因是JavaScript是單線程的。頁面的繪圖發生在與數據處理相同的線程上。所以如果你有一塊需要很長時間處理的數據,你會遇到用戶界面死機。

請看下面的例子:

http://jsfiddle.net/VT4Rs/

注:您可能需要垃圾郵件的「STOP」按鈕有點如果屏幕是凍結的,當你點擊它。此外,如果您的計算機/瀏覽器不如我的好,或者您的計算機/瀏覽器比我的更棒,那麼您可能需要調整「WEIGHT」變量以防止超長時間凍結。

無論如何,重要的是你會注意到,「Clock」會在所有這些數字循環時定期凍結。原因是因爲時鐘更新與數據「處理」在同一個線程上發生。 setInterval()的工作方式,它會每X毫秒將一個事件(運行它傳遞的函數)添加到事件隊列中。但是,爲了防止在函數運行超過X毫秒的情況下出現一些嚴重問題,如果先前的事件迭代已經在隊列中,它將跳過向事件隊列中添加新事件。

所以,如果你有一些隨機處理,佔用你的線程,那麼你的setInterval s將顯然工作不當。另外,由於瀏覽器界面在同一個線程中更新,因此您也可能導致「凍結」。

我發現解決這個問題的最好方法是將數據處理分解爲更易於管理的「塊」,然後使用setTimeout(fn, 0)定期將這些塊推入事件隊列,同時允許某些瀏覽器繪畫和其他JavaScript處理如所須。所以看看這個更新的例子,看看它們的區別。我們仍在「處理」相同的數據,但我們把它分成小塊:

http://jsfiddle.net/Sjk29/

訣竅成爲決定如何大,使塊。你會發現將塊調整得太大會導致失速和間隔。但是如果它太小,則由於每個塊的內置開銷,處理數據需要花費很長時間。

好消息是,您不會受限於指定的大小。在我的例子中,塊的大小由一個變量決定,你可能會注意到每個塊都引用了這個變量。這意味着您可以調整該變量以調整塊大小,具體取決於用戶瀏覽器上的實際性能。你可能會做這樣的事情:

var CHUNK_SCALE = 8; 
var CHUNK_SIZE = function() { return Math.pow(10, CHUNK_SCALE); }; 

(function() { 
    var lastTick = new Date(); 

    setInterval(function() { 
     var now = new Date(); 
     if (now - lastTick > 1500) { 
      CHUNK_SCALE--; 
     } 
     lastTick = now; 
    }, 1000); 
}()); 

(參見:http://jsfiddle.net/ewP96/

這樣一來,如果塊大小開出過大(的方式,可能會影響用戶界面性能),然後它會自動調整它回到用戶的電腦可以處理的東西。

JavaScript非常棒,呃?

+0

+1爲偉大的答案! –

+0

很棒的答案。我唯一的問題是,將django HTTP響應分成塊的最簡單方法是什麼,以及我將使用什麼代碼來檢索AJAX中的塊?再次感謝! – user1094786