Оптимизация Javascript-кода

Написана 3 Января, 2009 в 3:09. Автор: borN_free   |   Теги: javascript, оптимизация Комментарии 1

Доброе время суток, дорогие читатели.

Heading/Alt Text Первый пост я хочу сразу же начать с темы, касающейся вплотную программирования - оптимизации javascript-кода.

На практике я столкнулся с весьма неприятной ситуацией, когда надо было обрабатывать порядка 5000 элементов checkbox, выставляя им массово параметр checked. Все бы хорошо, если бы не наш любимый браузер IE, которые выполнял это действие порядка тридцати секунд, и естественно вся страница зависала на это время.

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

function doSelect () {
    var step = 150;
    var is_checked = $('#selector').attr('checked');
    var check = document.getElementsByName('product_selected{$append}[]');
    var from = 0;
    (function () {
        if ((from + step) > check.length) {
            loop_to = check.length;
        } else {
            loop_to = from + step;
        }
        for (var i = from; i < loop_to; i++) {
            check[i].checked = is_checked;
        }
        from += step;
        if (from <= check.length) {
            setTimeout(arguments.callee, 0);
        }
    })();
}

Как вы знаете, Javascript - однопоточный язык. Но с помощью функции setTimeout мы можем добиться того, чтобы браузер обновлял интерфейс так часто, как это будет запрограммировано, тем самым позволяя избегать вышеописанных проблем.

Итак, инициализируем необходимые нам переменные:

// количество итераций в одном "потоке"
var step = 150;
// выделяем или снимаем выделение с элементов срeckbox
var is_checked = $('#selector').attr('checked');
// коллекция элементов checkbox
var check = document.getElementsByName('product_selected{$append}[]');
// цикл начинаем с нуля
var from = 0;

Далее идут проверки выхода за предел коллекции - не представляющий интереса код.

if ((from + step) > check.length) {
    loop_to = check.length;
} else {
    loop_to = from + step;
}

И, наконец, самое интересное:

// непосредственно активируем либо деактивируем checkbox
for (var i = from; i < loop_to; i++) {
    check[i].checked = is_checked;
}
// каждый "поток" начинаем с определеного элемента (помните, шаг у нас 150)
from += step;
if (from <= check.length) {
    // вот главное место. Вызываем опять нашу функцию, 
    // и браузер отрисовывает страницу 
    setTimeout(arguments.callee, 0);
}

В итоге оптимизация данного куска javascript-кода уменьшила время выполнения по результатам теста до 0.1ms.

One comment

+8 ответить
Jacket:
December 31, 2011 at 11:22 am

спасибо, пригодилось

Оставьте свой комментарий:

Поля с * обязательны.