2012-11-09 74 views
1

根據以前在類似的問題上提出的問題,我可以推斷,由於Javascript是單線程的,像setTimeout這樣的方法可能會考慮到,但我似乎沒有得到任何漸進結果。我的任務涉及DOM操作,所以我不能依賴HTML5 Web WorkersJavaScript運行密集的可視化操作而不會凍結瀏覽器

這裏的問題是繪製大數據集以進行統計操作,如Resampling.For其中我們使用d3庫,在整個數據集中,並計算圖的各種參數,如箱數,比例等。圍繞冗長循環的一種方式是將數據集分解爲更小的塊,但仍然需要立即傳遞整個數據集以計算參數i是瓶頸。

我所指的一個很好的例子是用於生成github庫(例如,https://github.com/mbostock/d3/graphs/contributors)的圖形。我們可以看到,儘管作爲一個密集型任務,繪圖操作不會干擾瀏覽器。任何線索如何在類似的線路上工作?

+0

是我的回答有幫助? – meetamit

回答

2

(我不知道,你鏈接的圖形資格作爲一個密集的任務,但不管)

我已經打破了使用超時的任務得到了較好的效果。假設你正在做這樣的事情:

var largeSelection = d3.selectAll('svg circle') 
    .data(aReallyLargeDataset);// Expensive Bind Operation 

largeSelection.enter() 
    .append('circle')// Lots of appending 
    .attr('r', function() { /* expensive calculations */ return ... }); 

largeSelection// Many refreshes 
    .attr('cx', function() { /* more expensive calculations */ return ... }); 

這可能需要在瀏覽器1秒渲染(很長一段時間,考慮到一切都將在此任務期間被凍結)。你可以通過這樣分解來改善它:

setTimeout(function() { 
    var largeSelection = d3.selectAll('svg circle') 
    .data(aReallyLargeDataset);// Expensive Bind Operation 

    setTimeout(function() { 
    largeSelection.enter() 
     .append('circle')// Lots of appending 
     .attr('r', function() { /* expensive calculations */ return ... }); 

    setTimeout(function() { 
     largeSelection// Many refreshes 
     .attr('cx', function() { /* more expensive calculations */ return ... }); 
    }, 100); 

    }, 100); 

}, 100); 

對不起,討厭的嵌套和超時。您可以以更具可讀性/可擴展性的方式重構/抽象它。無論如何,以這種方式分解任務使瀏覽器有機會「呼吸」並更新DOM,從用戶的角度看,應用程序似乎不會「卡住」。

如果仍然感覺呆滯,你可以打破上去更:

var entering = largeSelection.enter() 
    .append('circle');// Lots of appending 

    setTimeout(function() { 
    entering.attr('r', function() { /* expensive calculations */ return ... }); 
    }, 100); 
+0

對於遲到的迴應,看到您熟悉d3,我已經提取了部分我在[jsfiddle](http://jsfiddle.net/sGnEY/)上可用的代碼。您會發現,你以很多圓圈的形式不是問題,它是直方圖參數binSize,區間和bin數,所有這些都是通過單個d3.layout.histogram方法計算的。我已經提到在setTimeout中包裝這將不會有太大的幫助 –

+0

嘿。不知道:你提供的jsFiddle應該是可運行的嗎? (它會引發錯誤)。創建直方圖佈局的行(您標記爲「昂貴的操作」),實際需要多長時間?即如果你把'var t0 = Date.now();'放在它之前,然後'console.log(Date.now() - t0,'毫秒')',你會得到什麼?如果超過100毫秒,那麼你需要重寫它來分解它。這樣做會涉及將佈局代碼從d3源代碼中複製出來,並創建一個自定義佈局,該佈局異步計算並在完成時調用回調。 – meetamit