admin管理员组

文章数量:1277895

I have a large set of data to be plotted on google map. Because of the data set size, google map always freezes for a few seconds before all the points are plotted. I used an animated spinning circle during the loading time to show it's in progress. But end users prefer to see actions. They want data plotted on the map step by step, instead of all at a once. Since javascript doesn't support multithreading, what's the best way to approach this?

I have a large set of data to be plotted on google map. Because of the data set size, google map always freezes for a few seconds before all the points are plotted. I used an animated spinning circle during the loading time to show it's in progress. But end users prefer to see actions. They want data plotted on the map step by step, instead of all at a once. Since javascript doesn't support multithreading, what's the best way to approach this?

Share Improve this question asked Jun 5, 2009 at 19:50 swingfutureswingfuture 1,1082 gold badges14 silver badges22 bronze badges 1
  • I've not messed with Google Maps. How much of this is in your control and how much of it is in Google's? – Nosredna Commented Jun 5, 2009 at 21:21
Add a ment  | 

4 Answers 4

Reset to default 7

Javascript engine executes functions one by one by taking them from sort of a queue. Functions can be put there either by your script or as result of user's actions (event handlers). So idea is to split long-running task into small short-running subtasks and feed them into this 'queue' in the manner so they can be mixed with functions responding to user's action.
This can be done by calling window's setTimeout with zero delay and passing your sub-task as a function. Thus you will give a chance for UI event handler to be executed earlier

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

Here is extension for Array 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();
};

Usage example (you have to have div with id 'spots' somewhere in document). To see the difference, set batch size equal to number of spots:

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 ? '; ' : '');
});

Could you plot them in batches, with a short delay (setTimeout) between each one?

Javascript might not support multiple threads normally, but you can achieve the effect.

function spawnThread(func, params){
   window.setTimeout(
      (function(f, p){
        return function(){
          f.call(p);
        }
      )(func, params), 0
   )
 }

The main problem with this method would, of course, be checking on the success of the thread, I assume you could manage this using a global variable or something similar, wouldn't be a great solution, but it would work.

Similar to what musicfreak said, but doesn't require Gears, is Javascript web workers. This is only implemented in the latest versions of browsers for now though.

本文标签: user interfaceUI responsiveness and javascriptStack Overflow