Отзывчивость пользовательского интерфейса и JavaScript - PullRequest
4 голосов
/ 05 июня 2009

У меня есть большой набор данных, которые будут нанесены на карту Google. Из-за размера набора данных карта Google всегда останавливается на несколько секунд, прежде чем начисляются все точки. Я использовал анимированный кружок во время загрузки, чтобы показать, что он в процессе. Но конечные пользователи предпочитают видеть действия. Они хотят, чтобы данные наносились на карту шаг за шагом, а не все сразу. Поскольку javascript не поддерживает многопоточность, как лучше всего подойти к этому?

Ответы [ 4 ]

7 голосов
/ 06 июня 2009

Javascript Engine выполняет функции одну за другой, отбирая их из очереди. Функции могут быть помещены туда либо вашим скриптом, либо как результат действий пользователя (обработчики событий). Поэтому идея состоит в том, чтобы разбить долгосрочную задачу на маленькие краткосрочные подзадачи и передать их в эту «очередь» таким образом, чтобы они могли быть смешаны с функциями, реагирующими на действия пользователя. Это можно сделать, вызвав setTimeout окна с нулевой задержкой и передав вашу подзадачу как функцию. Таким образом, вы дадите возможность выполнению обработчика событий пользовательского интерфейса раньше

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

Вот расширение для прототипа Array:

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

Пример использования (где-то в документе должен быть div с id 'spot'). Чтобы увидеть разницу, установите размер партии равным количеству точек:

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 ? '; ' : '');
});
4 голосов
/ 05 июня 2009

Javascript может не поддерживать несколько потоков в обычном режиме, но вы можете добиться эффекта.

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

Основной проблемой этого метода, конечно же, будет проверка успешности потока. Я предполагаю, что вы могли бы справиться с этим с помощью глобальной переменной или чего-то подобного, не было бы отличным решением, но это работало бы.

4 голосов
/ 05 июня 2009

Не могли бы вы построить их партиями, с небольшой задержкой (setTimeout) между каждым?

1 голос
/ 06 июня 2009

Подобно тому, что сказал musicfreak, но не требует Gears, веб-работники Javascript . Пока это реализовано только в последних версиях браузеров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...