Сортировка jQuery, вызывающая замораживание iOS Safari
У меня есть страница, использующая jQuery для загрузки XML файла, который затем выводит содержимое страницы.
Недавно я добавил функцию сортировки для вывода, которая вызывает 1+ или 2+ минуты в Safari на iPod Touch (в зависимости от того, сколько полей я сортирую) и менее 1 минуты висит на iPad. Тот же вид возвращается в течение нескольких секунд в Firefox 4.0.1.
Я боюсь, что это просто ограничение iOS, но до того, как я удалил сортировку, возможно, была сделана оптимизация.
Перед фильтром есть 357 элементов в XML. После фильтра есть 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-устройство или я могу оптимизировать свой вид?
Ответы
Ответ 1
Каждый раз, когда вы выполняете $(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();
делать:
var firstSystem = first.data('system');
if (!firstSystem) {
firstSystem = (first.find("console").text() + " " + first.find("version").text()).toLowerCase();
first.data('system') = firstSystem;
}
Ответ 2
Вы должны переместить любые вызовы селекторов следующим образом:
var firstTitle = $(a).find('title').text().toLowerCase();
из функции компаратора. Функция компаратора должна быть легкой.
Использовать children()
, next()
и т.п. или
сканирование, которое вы установили один раз, и создать массив ключей вверх, а затем отсортировать его с помощью этих клавиш.
Функция компаратора будет называться 2n * ln(n)
times (зависит от используемого алгоритма), где n
- это количество элементов в наборе. Таким образом, ваш код делает как минимум два дорогостоящих вычисления.