重大计算和显示数据而不会阻止UI

时间:2017-07-11 12:38:32

标签: javascript user-interface d3.js nonblocking web-worker

我正在开发一个应用程序,它将进行统计计算,然后用D3.js显示结果数据。

在大多数情况下,我可以通过将实际计算传递给WebWorker来避免阻止UI。

完成计算后,数据点将排序并显示为d3.js.使用WebWorker中的DOM元素是令人讨厌的(though possible),即使工作者本身无法与DOM交互。我还是真的想避免这种情况。

我们说我有大约100万个数据点,它们将用d3进行排序和显示。 当js执行此任务时,如何避免UI冻结?

一个想法,在某种程度上有效:

d3代码看起来像这样:

d3.select ...
.sort ...
.enter ...
.attr ...
.attr ...
.style ...

这将全部执行一次。为了让render queue有机会在事物之间进行渲染,你可以做这样的事情:

 let prom = new Promise((re, rj) => {
            setTimeout(function() {
                let val = d3.select ...
                            .sort ...
                            .enter ...
                re(val);            
              }, 0);
        });

prom.then(val => {
    val = val.attr ...
            .attr ...
            .style ...
}); 

数据的d3操作的第一部分将被推送到回调队列,渲染队列有机会渲染,然后d3代码的下一部分将被执行(具有多个promise的更复杂的模型)可能)。仍然无法解决问题。它可能比一次执行所有内容要好一些,但如果单个部件本身耗时太长,UI仍将冻结。

有没有人知道这个问题的好方法?

2 个答案:

答案 0 :(得分:1)

问题是您正在使用SVG,它必须添加Dom元素来表示您的所有条形图。即使您使用Web工作人员进行繁重的处理,添加数千个Dom元素,计算图像和绘制也是锁定主线程的原因。

你可以通过使用canvas来帮助解决这个问题,而不会出现大量的Dom元素并且更多地使用GPU。 D3 V4支持canvas,但需要一些重新架构才能使它工作。您也可以逐步渲染。棘手的一点是添加你的互动,因为你也没有单独的元素来附加听众。

答案 1 :(得分:0)

正如艾略特已经指出的那样,问题是D3会为DOM添加这么多元素。为了避免阻塞主线程,可以以块为单位绘制数据,如建议的here

我仍然需要先排序。