Запуск скриптов, требующих значительного времени выполнения.
Большим препятствием для запуска скриптов, которые выполняются продолжительное время, является тот факт, что в JavaScript нет многопотоковой обработки. Это значит, что окно браузера не отвечает на события пользователя до тех пор, пока выполняющийся скрипт не закончит своей работы. Следовательно, скрипты, которые выполняются 1, 2 или более секунд, "замораживают" пользовательский интерфейс, что не совсем приятно для пользователя.
Кроме того, браузеры имеют ограничение на продолжительность выполнения скриптов. Если скрипт выполняется дольше лимита, предостовляемого браузером для выполнения, то появляется окно, предлагающая прервать выполнение скрипта.
Для того, чтобы выполнять такие скрипты, можно использовать функцию setTimout, которая позволяет выполнять код с задержкой, позволяя браузеру при этом обрабатывать события и обновлять интерфейс даже в том случае, если задержка равна нулю.
Ниже представлены 2 шаблона функций для выполнения подобных операций:
function doSomething(callback [, аргументы]) {
// Инициализация
(function () {
// тело цикла
// ...
if (условие остановки цикла) {
// callback вызывается при завершении работы цикла
callback();
} else {
// следующая итерация
setTimeout(arguments.callee, 0);
}
})();
}
function doSomethingPro(progress [, аргументы]) {
// Инициализация
(function () {
// тело цикла
// ...
if (условие продолжения цикла) {
// progress вызывается при каждой итерации цикла
progress();
setTimeout(arguments.callee, 0);
}
})();
}Первая функция принимает указатель на функцию callback и выполняет её по завершинию операции, вторая получает указатель на функцию progress, которая выполняется при каждом проходе цикла.
Теперь рассмотрим пример. В приведенном ниже листинге создаётся таблица размером 400 строк по 10 ячеек в каждой:
<html>
<head>
<title>Скрипт</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript">
// создание строки
function createRow(count){
var row = document.createElement("tr");
row.className = "the_row";
row.setAttribute("id", "row_number_"+count);
for (var i=0; i<10; i++){
var cell = document.createElement("td");
cell.setAttribute("width", "10%");
cell.setAttribute("bgcolor", "#EEEEEE");
cell.setAttribute("align", "left");
cell.setAttribute("style", "font-size:10px;color:#333");
cell.className = "the_cell";
cell.setAttribute("id", "the_cell_"+count+"_"+i);
cell.appendChild(document.createTextNode("Строка: "+count+" Ячейка: "+i));
row.appendChild(cell);
}
return row;
}
// создание таблицы
function createTable(){
var table = document.createElement("table");
table.setAttribute("id", "the_table");
table.setAttribute("bgcolor", "#FFFFFF");
table.setAttribute("border", "1");
table.setAttribute("cellpadding", "0");
table.setAttribute("cellspacing", "0");
// Выполнение этого цикла занимает продолжительное время -
// он создаёт 400 строк таблицы с 10 ячейками в каждой
for (var i=0; i<400; i++){
var row = createRow(i);
table.appendChild(row);
}
var body = document.getElementsByTagName('body')[0];
body.appendChild(table);
}
window.onload = createTable;
</script>
</head>
<body>
</body>
</html>Теперь преобразуем функцию createTable() таким образом чтобы окно браузера не "замерзало" при выполнении столь длительной операции:
function createTable(){
var table = document.createElement("table");
table.setAttribute("id", "the_table");
table.setAttribute("bgcolor", "#FFFFFF");
table.setAttribute("border", "1");
table.setAttribute("cellpadding", "0");
table.setAttribute("cellspacing", "0");
var count = 0;
(function () {
// тело цикла
var row = createRow(count);
table.appendChild(row);
if (count == 400) {
// Завершение работы цикла
// Таблица создана, добавляем её в документ
var body = document.getElementsByTagName("body")[0];
body.appendChild(table);
} else {
// следующая итерация
count++;
setTimeout(arguments.callee, 0);
}
})();
}Здесь при каждой итерации цикла, счетчик count увеличивается на единицу, а при завершении работы созданная таблица добавляется в тэг body. Пример с использованием прогресс бара можно посмотреть здесь.
20 февраля 2008 в 17:42
Очень хорошая статья!! Сильно помогла в трудную минуту. Спасибо!…