1

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

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

我所指的一个很好的例子是用于生成 github 存储库的图形(例如,https ://github.com/mbostock/d3/graphs/contributors )。我们可以看到绘图操作不会干扰尽管是一项繁重的任务,但使用浏览器。关于如何在类似的线路上工作的任何线索?

4

1 回答 1

2

(I'm not sure that the graphs you linked to qualify as an intensive task, but regardless)

I've gotten good results by breaking up the tasks using timeouts. Say you're doing something like this:

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

That might take the browser 1 second to render (a long time, considering everything will be frozen during this task). You can make it better by breaking it up like so:

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

Sorry about the obnoxious nesting and timeouts. You could refactor/abstract it in a way that's more readable/scalable. In any case, breaking up the tasks this way gives the browser a chance to "breath" and update the DOM so that, from the user's perspective, the application doesn't seem "stuck".

If that still feels sluggish, you can break things up even more:

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

  setTimeout(function() {
    entering.attr('r', function() { /* expensive calculations */ return ... });
  }, 100);
于 2012-11-09T19:33:09.090 回答