ОБНОВЛЕНИЕ: проблема загадочно исчезла после длинной сессии jslint, поэтому я должен сделать вывод, что это была какая-то глупая ошибка где-то в моем коде, которая была исправлена удалив некоторые, по-видимому, безобидные опечатки.AJAX вызов кеширования через Promise делает использование браузера CPU (и память утечки)
Первоначальной проблема
У меня есть страница, которая загружает значительное (и случайно переменное) количество объектов AJAX с помощью JQuery .post
вызовов.
Так что я бы генерировать много вызовов, таких как
/entry/get/orange
/entry/get/red
/entry/get/yellow
/entry/get/red <--- duplicate!
/entry/get/red <--- again!
/entry/get/yellow
/entry/get/red <--- dude, what's wrong with you?
...
При работе таким образом, что все работает как надо, помимо того, что на самом деле, очень неэффективно, и попав на сервер довольно понапрасну ,
попытка решения
Так что я перешел на кэширование через Promise, как это:
// I have a global colorCache variable
function retrieve(color, callback) {
console.log("retrieving " + color);
var found = -1;
// Each entry in colorCache is an object with some other values
for (var i in colorCache) {
if (colorCache[i].color === color) {
found = i;
break;
}
}
if (found < 0) {
console.log("effecting call for " + color);
var url = "blah/blah/blah/" + color;
var ppar = {
foo: "bar",
answer: 42
};
/* push returns the new length of colorCache */
found = colorCache.push({
color : color,
promise : $.post(url, ppar),
ts : new Date().getTime()
}) - 1;
} else {
console.log("cache hit for " + color);
}
// now found is valid. Return the Promise too, for appending.
return colorCache[found].success(callback);
}
Таким образом, если соответствующий .post
уже выдан, обратный вызов снова вызывается с теми же данными, является ли сам вызов уже завершен или все еще продолжается.
Снова все работает. Видимо.
Теперь у меня есть другого проблема
С этой новой версией,
- страница загружается
- все объекты загружаются (намного быстрее, чем раньше, - как и следовало ожидать)
- страницы останавливается, все еще ... нет анимаций, нет часов, ничего ...
- ... но Process Explorer теперь показывает Firefox постоянно ест 26-30% от CPU. И будет продолжить, чтобы сделать это до тех пор, пока я не закрою вкладку, на которой загружена страница. Кроме того, Потребление памяти в Firefox постоянно растет. Я наблюдал, как он поднимался с 800 м до 1,7 ГБ за чуть меньше часа, а не полностью регулярно, но с заметным восходящим трендом.
В чем проблема?
Важное примечание: есть несколько «утечка браузера» вопросы и ответы на переполнение стека, но все они связаны повторил JQuery вызовы, выделять объекты или перебирать в некотором роде. Здесь, как только я запустил пятьдесят вызовов jQuery, ничего больше не происходит. не
То, что я пытался (до сих пор)
- Я проверил с Firebug: нет консольного предупреждения или ошибок, не сигнальных журналов (все функций я называю есть), никакой сетевой активность (двойная - проверяется с сервера сервера Apache).
- Я просмотрел процесс Firefox в памяти; основной поток запущен, но я не очень хорошо разбираюсь в потоковой информации Process Explorer - он показывает что-то о «forInIterator», которое мало мне подсказывает.
- Отсутствует активность, за исключением процессора (сеть, чтение/запись реестра Windows).
- Я немного искал Google, и нашел something возможно связанный (но, возможно, нет). Я еще не пробовал это предложение, но я сделаю это в ближайшее время, даже если я не вижу, как он может помочь, и в любом случае я не использую
when.js
, даже если что-то подобное может заполнить jQuery с: Одним из возможных способов обхода является обеспечение того, что ваши обратные вызовы и возвратные функции возвращают что-то (кроме $ .Deferred). - завернул вызов .post с помощью Promise.resolve, как предложил Jaromanda X, и переместил объект кеша внутри функции, чтобы избежать загрязнения глобальной области (что всегда является хорошей практикой).
- Вернул непосредственно объект Promise и вызвал обратный вызов путем добавления внешнего. Then.
- Протестировано с помощью Chrome. Те же результаты (в некотором смысле это обнадеживающие), за исключением того, что загрузка процессора постоянна на 17%.
- Закрытие вкладки делает загрузку процессора выключенной.
Вам не нужно: return colorCache [found] .promise.then (callback); '? 'colorCache [found]' - это ваш объект, который не имеет метода '.success()', который вы пытались вызвать. Кроме того, я переключился на '.then()', чтобы быть намного более совместимым с будущим, поскольку '.success()' нестандартен. – jfriend00
Я читал * jQuery.deferred * не совсем Promise/A + spec - это не значит, что это источник этой проблемы, однако попробуйте «обернуть» '.post (url, ppar)' в native 'Promise.resolve ($. Post (url, ppar))' и посмотреть, не исчезла ли проблема использования процессора - также вот [скрипка] (https://jsfiddle.net/6qr4rx65/) вашей функции извлечения, которая не работает 't нужна глобальная переменная и упрощает (я думаю) логику (нет для циклов для поиска кешированных значений, например) - скрипка обертывает jQuery, как указано в этом комментарии –
@JaromandaX, я пробовал, но не работал , Теперь я попытаюсь уменьшить количество вызовов и посмотреть, не потеряет ли это ключ. – LSerni