У меня есть веб-страница, которая пропускает память как в IE8, так и в Firefox; использование памяти, отображаемое в Проводнике Windows, просто растет с течением времени.
Следующая страница запрашивает url "unplanned.json", который является статическим файлом, который никогда не изменяется (хотя я устанавливаю свой HTTP-заголовок Cache-control
на no-cache
, чтобы убедиться, что запрос Ajax всегда проходит). Когда он получает результаты, он очищает таблицу HTML, перебирает массив json, полученный с сервера, и динамически добавляет строку в таблицу HTML для каждой записи в массиве. Затем он ждет 2 секунды и повторяет этот процесс.
Здесь вся веб-страница:
<html> <head>
<title>Test Page</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
</head> <body>
<script type="text/javascript">
function kickoff() {
$.getJSON("unplanned.json", resetTable);
}
function resetTable(rows) {
$("#content tbody").empty();
for(var i=0; i<rows.length; i++) {
$("<tr>"
+ "<td>" + rows[i].mpe_name + "</td>"
+ "<td>" + rows[i].bin + "</td>"
+ "<td>" + rows[i].request_time + "</td>"
+ "<td>" + rows[i].filtered_delta + "</td>"
+ "<td>" + rows[i].failed_delta + "</td>"
+ "</tr>").appendTo("#content tbody");
}
setTimeout(kickoff, 2000);
}
$(kickoff);
</script>
<table id="content" border="1" style="width:100% ; text-align:center">
<thead><tr>
<th>MPE</th> <th>Bin</th> <th>When</th> <th>Filtered</th> <th>Failed</th>
</tr></thead>
<tbody></tbody>
</table>
</body> </html>
Если это помогает, вот пример json, который я отправляю обратно (это этот массив с тысячами записей вместо одного):
[
{
mpe_name: "DBOSS-995",
request_time: "09/18/2009 11:51:06",
bin: 4,
filtered_delta: 1,
failed_delta: 1
}
]
EDIT: я принял Торан чрезвычайно полезный ответ, но я чувствую, что должен опубликовать дополнительный код, так как его плагин removefromdom
jQuery имеет некоторые ограничения:
- Он удаляет только отдельные элементы. Поэтому вы не можете дать ему запрос типа `$ ( "# content tbody tr" )` и ожидать, что он удалит все указанные вами элементы.
- Любой элемент, который вы удаляете с ним, должен иметь атрибут id. Поэтому, если я хочу удалить "tbody", тогда я должен назначить "id" для моего тега tbody, иначе он выдаст ошибку.
- Он удаляет сам элемент и все его потомки, поэтому, если вы просто хотите опорожнить этот элемент, вам придется его повторно создать (или изменить плагин для удаления вместо удаления).
Итак, здесь моя страница выше, чтобы использовать плагин Toran. Для простоты я не применил ни один из общих рекомендаций по производительности предложенных Peter. Здесь страница, которая теперь больше не утечка памяти:
<html>
<head>
<title>Test Page</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
<!--
$.fn.removefromdom = function(s) {
if (!this) return;
var el = document.getElementById(this.attr("id"));
if (!el) return;
var bin = document.getElementById("IELeakGarbageBin");
//before deleting el, recursively delete all of its children.
while (el.childNodes.length > 0) {
if (!bin) {
bin = document.createElement("DIV");
bin.id = "IELeakGarbageBin";
document.body.appendChild(bin);
}
bin.appendChild(el.childNodes[el.childNodes.length - 1]);
bin.innerHTML = "";
}
el.parentNode.removeChild(el);
if (!bin) {
bin = document.createElement("DIV");
bin.id = "IELeakGarbageBin";
document.body.appendChild(bin);
}
bin.appendChild(el);
bin.innerHTML = "";
};
var resets = 0;
function kickoff() {
$.getJSON("unplanned.json", resetTable);
}
function resetTable(rows) {
$("#content tbody").removefromdom();
$("#content").append('<tbody id="id_field_required"></tbody>');
for(var i=0; i<rows.length; i++) {
$("#content tbody").append("<tr><td>" + rows[i].mpe_name + "</td>"
+ "<td>" + rows[i].bin + "</td>"
+ "<td>" + rows[i].request_time + "</td>"
+ "<td>" + rows[i].filtered_delta + "</td>"
+ "<td>" + rows[i].failed_delta + "</td></tr>");
}
resets++;
$("#message").html("Content set this many times: " + resets);
setTimeout(kickoff, 2000);
}
$(kickoff);
// -->
</script>
<div id="message" style="color:red"></div>
<table id="content" border="1" style="width:100% ; text-align:center">
<thead><tr>
<th>MPE</th>
<th>Bin</th>
<th>When</th>
<th>Filtered</th>
<th>Failed</th>
</tr></thead>
<tbody id="id_field_required"></tbody>
</table>
</body>
</html>
ДАЛЬНЕЙШЕЕ ИЗМЕНЕНИЕ: Я оставлю свой вопрос без изменений, хотя стоит отметить, что эта утечка памяти не имеет ничего общего с Ajax. Фактически, следующий код будет утечкой памяти точно так же и будет так же легко решен с Toran removefromdom
плагин jQuery:
function resetTable() {
$("#content tbody").empty();
for(var i=0; i<1000; i++) {
$("#content tbody").append("<tr><td>" + "DBOSS-095" + "</td>"
+ "<td>" + 4 + "</td>"
+ "<td>" + "09/18/2009 11:51:06" + "</td>"
+ "<td>" + 1 + "</td>"
+ "<td>" + 1 + "</td></tr>");
}
setTimeout(resetTable, 2000);
}
$(resetTable);