Обработка больших объемов данных в JavaScript

в категориях:
Версия для печатиВерсия для печати

В предыдущей статье мы изучали время выполнения JavaScript в браузерах и их ограничения, а также методы, которые могут помочь избежать появления сообщений вида "Скрипт не отвечает" в браузере. Мы рассмотрели метод псевдо-потоков, основанный на времени выполнения. Теперь мы будем искать способ обработки больших массивов данных в браузерах.

Несколько лет назад разработчики даже не задумывались об альтернативах сложной обработки данных на стороне сервера. Теперь же все изменилось, и многие Ajax-приложения обмениваются большим количеством данных между клиентом и сервером. Кроме того, программный код приложения может изменять объектную модель документа (DOM), что требует особенно много времени для обработки браузером. Однако, попытка обработки больших объемов информации за один раз может привести к зависанию приложения и принудительному завершению работы приложения со стороны браузера.

Таймеры, существующие в JavaScript, могут помочь предотвратить блокировку приложения браузером благодаря разделению длительных по времени процессов обработки данных на небольшие блоки. Вот наша функция обработки больших массивов с данными:

function ProcessArray(data, handler, callback) { 

Функция ProcessArray() имеет три аргумента:

  • data: массив элементов для обработки;
  • handler: функция, применяемая для обработки каждого отдельного элемента массива;
  • callback: дополнительная функция, вызываемая после полной обработки массива.

Теперь мы определим переменные конфигурации:

  var maxtime = 100; // время обработки блоков массива
  var delay = 20; // задержка между двумя процессами обработки блоков
  var queue = data.concat(); // копия исходного массива

Переменная maxtime определяет максимальное время в миллисекундах, разрешенное для обработки каждого блока массива. Переменная delay задает время в миллисекундах между процессами обработки отдельных блоков массива. Переменная queue является копией исходного массива с данными, в которой в принципе нет необходимости в большинстве случаев. Однако, так как массив передается в функцию по ссылке, и мы с каждой обработкой нового элемента выталкиваем его из массива функцией shift, эта копия в нашем случае нужна для сохранности данных исходного массива во время обработки.

Теперь мы можем использовать функцию setTimeout для начала обработки:

  setTimeout(function() {
    var endtime = +new Date() + maxtime;
    do {
      handler(queue.shift());
    } while (queue.length > 0 && endtime > +new Date());

Сначала вычисляется значение переменной endtime — время перкращения обработки. В цикле do…while происходит обработка элементов массива queue в порядке очереди, пока обработка массива полностью не завершится или же не будет достигнуто время остановки endtime.

Примечение: Зачем использовать цикл do…while?

В JavaScript поддерживается оба вида циклов while: while и do…while. Отличие между ними в том, что цикл do…while гарантирует нам выполнение хотя бы одной итерации цикла. Если же мы используем обычный цикл while, то цикл может даже и не начаться из-за недостаточного времени, указанного в переменной endtime.

Наконец, мы определяем, остались ли элементы в массиве, которые нужно обработать, и, если обработка необходима, вызываем функцию обработки массива после короткой задержки:

    if (queue.length > 0) {
      setTimeout(arguments.callee, delay);
    }
    else {
      if (callback) callback();
    }
  }, delay);
}
// конец функции ProcessArray

Функция callback выполнится один раз, после обработки всех элементов массива.

Теперь можно протестировать функцию ProcessArray() на сгенерированном наборе данных:

// обработка отдельного элемента массива
function Process(dataitem) {
  console.log(dataitem);
}
// функция, вызываемая после завершения обработки
function Done() {
  console.log("Готово");
}
// тестовые данные
var data = [];
for (var i = 0; i < 500; i++) data[i] = i;
// обработка элементов массива
ProcessArray(data, Process, Done);  

Приведенный код работает во всех браузерах, включая IE6+. Это эффективное кроссбраузерное решение, однако в будущем HTML5 предоставит нам более подходящее решение! В следующей статье мы рассмотрим многопоточность в HTML 5…

Статья основана на публикации "How to Process Large Volumes of Data in JavaScript".
Ваша оценка: Нет Средняя: 7.8 (5 голосов)