В моих предыдущих статьях мы рассмотрели ограничения на выполнение JavaScript и ограничения браузера, а также метод, который может обрабатывать предупреждения о «не отвечающих сценариях» с использованием псевдопоточности по таймеру . Сегодня мы рассмотрим способы обработки больших объемов данных в браузере.
Несколько лет назад разработчики никогда бы не рассмотрели альтернативы сложной обработке на стороне сервера. Это восприятие изменилось, и многие приложения Ajax отправляют огромные объемы данных между клиентом и сервером. Кроме того, код может обновить DOM, что является особенно трудоемким процессом браузера. Однако попытка проанализировать эту информацию за один раз может привести к тому, что приложение перестанет отвечать на запросы и выдать предупреждения сценария.
Таймеры JavaScript могут помочь предотвратить проблемы с блокировкой браузера, разбив длинный процесс анализа данных на более короткие порции. Вот начало нашей функции JavaScript:
function ProcessArray(data, handler, callback) {
Функция ProcessArray()
принимает три аргумента:
- данные: массив элементов для обработки
- обработчик: функция, которая обрабатывает отдельный элемент данных
- обратный вызов: необязательная функция, вызываемая, когда вся обработка завершена.
Далее мы определим переменные конфигурации:
var maxtime = 100; // chunk processing time var delay = 20; // delay between processes var queue = data.concat(); // clone original array
maxtime
указывает максимальное количество миллисекунд, разрешенное для каждого блока обработки. delay
— это время в миллисекундах между фрагментами обработки. Наконец, queue
клонирует исходный массив данных — это не будет необходимо во всех случаях, но, поскольку массив передается по ссылке, и мы отбрасываем каждый элемент, это самый безопасный вариант.
Теперь мы можем использовать setTimeout
чтобы начать обработку:
setTimeout(function() { var endtime = +new Date() + maxtime; do { handler(queue.shift()); } while (queue.length > 0 && endtime > +new Date());
Во-первых, endtime
— это будущее время, когда обработка должна прекратиться. Цикл do… while обрабатывает элементы в очереди по очереди и продолжается до тех пор, пока не завершится каждый элемент или не будет достигнут endtime
.
do…while?
JavaScript поддерживает как циклы while, так и циклы do… while. Разница в том, do…while
циклы do…while
гарантированно выполняют хотя бы одну итерацию. Если бы мы использовали стандартный цикл while, разработчик мог бы установить maxtime
или отрицательное maxtime
, и обработка массива никогда не началась бы или не завершилась.
Наконец, мы определяем, нужно ли обрабатывать дополнительные элементы, и, если необходимо, вызываем нашу функцию обработки после небольшой задержки:
if (queue.length > 0) { setTimeout(arguments.callee, delay); } else { if (callback) callback(); } }, delay); } // end of ProcessArray function
Функция обратного вызова выполняется после обработки каждого элемента.
Мы можем протестировать ProcessArray()
с помощью небольшого тестового примера:
// process an individual data item function Process(dataitem) { console.log(dataitem); } // processing is complete function Done() { console.log("Done"); } // test data var data = []; for (var i = 0; i < 500; i++) data[i] = i; // process all items ProcessArray(data, Process, Done);
Код будет работать в любом браузере, включая IE6 +. Это жизнеспособное кросс-браузерное решение, но HTML5 предоставляет гораздо более приятное решение! В моем следующем посте мы обсудим веб-работников …