我有一個網頁,顯示一個包含大量數據的圖表。該圖表是第三方Flash組件。JS中的網站加載結構
很多數據都是在加載初始頁面之後,在AJAX中延遲加載並輸入到圖表中的。我的問題是,雖然發生這種情況,頁面凍結多次,直到所有的數據加載。這是一個問題,尤其是因爲頁面加載,並且似乎所有內容都已準備就緒,但隨後在使用AJAX加載數據時,頁面會凍結。 一個很好的例子是setInterval我有每1秒遞增一個時鐘。此時鐘在AJAX加載過程中視覺凍結。
這怎麼可以避免?你會推薦一個不同的加載結構嗎?
我有一個網頁,顯示一個包含大量數據的圖表。該圖表是第三方Flash組件。JS中的網站加載結構
很多數據都是在加載初始頁面之後,在AJAX中延遲加載並輸入到圖表中的。我的問題是,雖然發生這種情況,頁面凍結多次,直到所有的數據加載。這是一個問題,尤其是因爲頁面加載,並且似乎所有內容都已準備就緒,但隨後在使用AJAX加載數據時,頁面會凍結。 一個很好的例子是setInterval我有每1秒遞增一個時鐘。此時鐘在AJAX加載過程中視覺凍結。
這怎麼可以避免?你會推薦一個不同的加載結構嗎?
你的問題其實很簡單,雖然解決方案有點棘手。您遇到「凍結」的原因是JavaScript是單線程的。頁面的繪圖發生在與數據處理相同的線程上。所以如果你有一塊需要很長時間處理的數據,你會遇到用戶界面死機。
請看下面的例子:
注:您可能需要垃圾郵件的「STOP」按鈕有點如果屏幕是凍結的,當你點擊它。此外,如果您的計算機/瀏覽器不如我的好,或者您的計算機/瀏覽器比我的更棒,那麼您可能需要調整「WEIGHT」變量以防止超長時間凍結。
無論如何,重要的是你會注意到,「Clock」會在所有這些數字循環時定期凍結。原因是因爲時鐘更新與數據「處理」在同一個線程上發生。 setInterval()
的工作方式,它會每X
毫秒將一個事件(運行它傳遞的函數)添加到事件隊列中。但是,爲了防止在函數運行超過X
毫秒的情況下出現一些嚴重問題,如果先前的事件迭代已經在隊列中,它將跳過向事件隊列中添加新事件。
所以,如果你有一些隨機處理,佔用你的線程,那麼你的setInterval
s將顯然工作不當。另外,由於瀏覽器界面在同一個線程中更新,因此您也可能導致「凍結」。
我發現解決這個問題的最好方法是將數據處理分解爲更易於管理的「塊」,然後使用setTimeout(fn, 0)
定期將這些塊推入事件隊列,同時允許某些瀏覽器繪畫和其他JavaScript處理如所須。所以看看這個更新的例子,看看它們的區別。我們仍在「處理」相同的數據,但我們把它分成小塊:
訣竅成爲決定如何大,使塊。你會發現將塊調整得太大會導致失速和間隔。但是如果它太小,則由於每個塊的內置開銷,處理數據需要花費很長時間。
好消息是,您不會受限於指定的大小。在我的例子中,塊的大小由一個變量決定,你可能會注意到每個塊都引用了這個變量。這意味着您可以調整該變量以調整塊大小,具體取決於用戶瀏覽器上的實際性能。你可能會做這樣的事情:
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非常棒,呃?
+1爲偉大的答案! –
很棒的答案。我唯一的問題是,將django HTTP響應分成塊的最簡單方法是什麼,以及我將使用什麼代碼來檢索AJAX中的塊?再次感謝! – user1094786
我建議你使用html5而不是flash來繪圖,這可能會解決你的凍結問題。 你可以查找:
如果我們需要加載大量數據,那麼「html5」不會自動幫助,需要有不同的方法 –
你能分享一些代碼? AJAX調用不應該阻止頁面,除非它不是異步的。 –
嗨,你可以加載頁面加載時的ajax數據。讓我們說,當頁面加載時,您可以在頁面中獲取json數據作爲javascript變量,並將該數據添加到您的Flash代碼中。簡而言之,您可以預先加載數據並以json格式存儲,而不是使用ajax調用。 –
我猜凍結髮生的原因是因爲很多數據被加載到Flash中,而不是因爲實際的AJAX請求... – user1094786