我有大量数据要绘制在谷歌地图上。由于数据集的大小,谷歌地图总是在绘制所有点之前卡住几秒钟。我在加载期间使用动画旋转圆圈来显示它正在进行中。但最终用户更喜欢看到操作。他们希望数据逐步绘制在 map 上,而不是一次全部绘制出来。由于 javascript 不支持多线程,解决这个问题的最佳方法是什么?
最佳答案
Javascript 引擎通过从某种队列中取出函数来一个接一个地执行函数。函数可以通过您的脚本或作为用户操作(事件处理程序)的结果放置在那里。所以想法是将长时间运行的任务拆分成小的短期运行的子任务,并以某种方式将它们送入这个“队列”,以便它们可以与响应用户操作的功能混合。
这可以通过以零延迟调用窗口的 setTimeout 并将您的子任务作为函数传递来完成。因此,您将有机会更早地执行 UI 事件处理程序
function plotSpot(spot) {
// adding spots to map
};
var spots = [1,2,3,4,5,6,7,8,9,10,11,12];
var plotSpotsBatch;
plotSpotsBatch = function() {
var spotsInBatch = 10;
while(spots.length > 0 && spotsInBatch--) {
var spot = spots.shift();
plotSpot(spot);
}
if (spots.length > 0) {
setTimeout(plotSpotsBatch, 0);
}
};
plotSpotsBatch();
这是数组原型(prototype)的扩展:
Array.prototype.forEachInBatches = function(batchSize, func) {
var arr = this;
var i = 0;
var doer;
doer = function() {
setTimeout(function() {
for (var stopBatch = i + batchSize; i < stopBatch && i < arr.length; i++) {
func(arr[i], i);
}
if (i < arr.length) {
doer();
}
}, 0);
};
doer();
};
用法示例(您必须在文档中的某处使用 ID 为“spots”的 div)。要查看差异,请将批量大小设置为等于点数:
var spots = [];
for (var i = 0; i < 10000; i++) {
spots.push('{x: ' + Math.ceil(Math.random() * 180) + ', y: ' + Math.ceil(Math.random() * 180) + '}');
}
spots.forEachInBatches(10, function(spot, i) {
document.getElementById('spots').innerHTML += spot + (i < spots.length ? '; ' : '');
});
关于javascript - UI响应和javascript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/957810/