从之前在类似行上提出的问题中,我可以推断,由于 Javascript 是单线程的,因此可能会考虑像 setTimeout 这样的方法,但是我似乎没有得到任何渐进的结果。我的任务涉及 DOM 操作,所以我可以'依赖 HTML5 Web Workers
这里的问题是关于为像重采样这样的统计操作绘制大数据集。为此我们使用 d3 库,一般来说,它接受整个数据集并计算图形的各种参数,如 bin 的数量,规模等。解决冗长循环的一种方法是将数据集分解成更小的 block ,但仍然必须立即传递整个数据集以计算参数,这是瓶颈。
我所指的一个很好的例子是用于生成 github 存储库的图表(例如,https://github.com/mbostock/d3/graphs/contributors)。正如我们所看到的,尽管是一项繁重的任务,但绘图操作不会干扰浏览器。关于如何处理类似线路的任何线索?
最佳答案
(我不确定您链接到的图表是否属于密集型任务,但无论如何)
通过使用超时分解任务,我获得了不错的结果。假设您正在做这样的事情:
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,这样,从用户的 Angular 来看,应用程序似乎不会“卡住”。
如果仍然感觉迟钝,您可以进一步分解:
var entering = largeSelection.enter()
.append('circle');// Lots of appending
setTimeout(function() {
entering.attr('r', function() { /* expensive calculations */ return ... });
}, 100);
关于Javascript运行密集型可视化操作而不卡住浏览器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13312988/