Сортировка jQuery приводит к зависанию iOS Safari - PullRequest
2 голосов
/ 08 мая 2011

У меня есть страница, которая использует jQuery для загрузки файла XML, который я затем выводю на страницу.

Недавно я добавил к выходу функцию сортировки, которая вызывает зависание на Safari на iPod Touch на 1+ или 2+ (в зависимости от того, сколько полей я сортирую) и зависание на iPad на 1 минуту. В Firefox 4.0.1 такая же сортировка возвращается через несколько секунд.

Боюсь, это всего лишь ограничение iOS, но, прежде чем я удалил сортировку, возможно, есть какая-то оптимизация, которую можно сделать.

Перед фильтром в XML содержится 357 элементов. После фильтра отсортировано 199 товаров.

var videoGames = $($.parseXML(videoGameXml)).find("game");
videoGames = videoGames.filter(function (a) {
    return ($(this).attr('addOn') != "true" && $(this).find('own').text() == "yes");
});
videoGames.sort(function (a, b) {
    var firstTitle = $(a).find('title').text().toLowerCase();
    var secondTitle = $(b).find('title').text().toLowerCase();
    var firstSystem = ($(a).find("console").text() + " " + $(a).find("version").text()).toLowerCase();
    var secondSystem = ($(b).find("console").text() + " " + $(b).find("version").text()).toLowerCase();

    if (firstSystem != secondSystem) {
        if (firstSystem > secondSystem) {
            return 1;
        } else {
            return -1;
        }
    } else {
        if (firstTitle > secondTitle) {
            return 1;
        } else if (secondTitle < firstTitle) {
            return -1;
        }
    }
    return 0;
});
videoGames.each(function () {
    // runs quickly, so removed
});

Обратите внимание, что если я уберу проверку системы как первоначальную «оптимизацию», которая сокращает время на iPod Touch примерно вдвое, но все равно приводит к зависанию на 1+ минуты, упомянутому выше.

Итак, это ограничение устройства iOS или я могу оптимизировать свой вид?

Ответы [ 2 ]

2 голосов
/ 08 мая 2011

Каждый раз, когда вы делаете $ (a), он выполняет очень сложный набор операций, поэтому вам лучше его кешировать. Кроме того, вам не нужен заголовок, если система отличается. Эта версия должна немного ускорить его:

videoGames.sort(function (a, b) {
    var first = $(a);
    var second = $(b);
    var firstSystem = (first.find("console").text() + " " + first.find("version").text()).toLowerCase();
    var secondSystem = (second.find("console").text() + " " + second.find("version").text()).toLowerCase();

    if (firstSystem != secondSystem) {
        if (firstSystem > secondSystem) {
            return 1;
        } else {
            return -1;
        }
    } else {
        var firstTitle = first.find('title').text().toLowerCase();
        var secondTitle = second.find('title').text().toLowerCase();

        if (firstTitle > secondTitle) {
            return 1;
        } else if (secondTitle < firstTitle) {
            return -1;
        }
    }
    return 0;
});

Вы также можете кэшировать значения в объекте

Тогда вместо:

var firstSystem = (first.find("console").text() + " " + first.find("version").text()).toLowerCase();

Do:

var firstSystem = first.data('system');
if (!firstSystem) {
    firstSystem = (first.find("console").text() + " " + first.find("version").text()).toLowerCase();
    first.data('system') = firstSystem;
}
1 голос
/ 08 мая 2011

Вы должны перемещать любые вызовы селекторов так:

var firstTitle = $(a).find('title').text().toLowerCase();

вне функции компаратора. Функция компаратора должна быть легкой.

Либо используйте children(), next() и т.п., либо отсканируйте один раз и создайте массив ключей заранее, а затем отсортируйте их по этим ключам.

Функция компаратора будет вызываться 2n * ln(n) раз (зависит от используемого алгоритма), где n - количество элементов в наборе. Таким образом, ваш код выполняет одни и те же дорогостоящие вычисления как минимум дважды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...