В предыдущей статье мы изучали время выполнения 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".Категории этой статьи
Опросы, близкие по теме
