Javascript运行密集的可视化操作而不冻结浏览器

Javascript运行密集的可视化操作而不冻结浏览器,javascript,d3.js,Javascript,D3.js,从之前在类似行中提出的问题中,我可以推断,由于Javascript是单线程的,所以可能会考虑使用setTimeout等方法,但我似乎没有得到任何渐进的结果。我的任务涉及DOM操作,因此我不能依赖HTML5 Web Workers 这里的问题是关于绘制大数据集以进行诸如重采样之类的统计操作。我们使用d3库,在一般情况下,它会接收整个数据集,并计算图形的各种参数,如箱数、比例等。绕过长循环的一种方法是将数据集分成更小的块,但仍然必须一次传递整个数据集以计算参数,这是瓶颈 我所指的一个很好的例子是用于

从之前在类似行中提出的问题中,我可以推断,由于Javascript是单线程的,所以可能会考虑使用setTimeout等方法,但我似乎没有得到任何渐进的结果。我的任务涉及DOM操作,因此我不能依赖HTML5 Web Workers

这里的问题是关于绘制大数据集以进行诸如重采样之类的统计操作。我们使用d3库,在一般情况下,它会接收整个数据集,并计算图形的各种参数,如箱数、比例等。绕过长循环的一种方法是将数据集分成更小的块,但仍然必须一次传递整个数据集以计算参数,这是瓶颈

我所指的一个很好的例子是用于生成github存储库(例如,)的图形。正如我们所看到的,尽管是一项密集的任务,但绘图操作不会干扰浏览器。关于在类似线路上工作有什么线索吗?

(我不确定您链接的图表是否符合密集型任务,但无论如何)

通过使用超时来分解任务,我得到了很好的结果。假设你正在做这样的事情:

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);

很抱歉反应太晚,因为您熟悉d3,所以我提取了我的部分代码。您知道,您以许多圆圈的形式假设的选择不是问题,而是直方图参数bin size、interval和bin的数量,所有这些都是通过单个d3.layout.histogram方法计算的。我提到过,用setTimeout包装这个东西不会有多大帮助。不确定:您提供的JSFIDLE应该是可运行的吗?(它抛出一个错误)。创建直方图布局的行(您标记为“昂贵的操作”),实际需要多长时间?也就是说,如果你把
var t0=Date.now()在它之前,然后是
console.log(Date.now()-t0,“毫秒”)
,你得到了什么?如果它超过100毫秒,那么您确实需要通过重写来打破它。这样做需要将布局代码从d3源代码中复制出来,并创建一个自定义布局,该布局异步计算自身,并在完成时调用回调。