Tôi có một trang web bị rò rỉ bộ nhớ trong cả IE8 và Firefox; việc sử dụng bộ nhớ được hiển thị trong Windows Process Explorer chỉ tiếp tục tăng theo thời gian.Rò rỉ bộ nhớ liên quan đến các yêu cầu jQuery Ajax
Trang sau yêu cầu url "unplanned.json", là tệp tĩnh không bao giờ thay đổi (mặc dù tôi đặt tiêu đề HTTP Cache-control
HTTP thành no-cache
để đảm bảo rằng yêu cầu Ajax luôn đi qua). Khi nó nhận được kết quả, nó sẽ xóa một bảng HTML, các vòng lặp trên mảng json mà nó lấy lại từ máy chủ và tự động thêm một hàng vào một bảng HTML cho mỗi mục nhập trong mảng. Sau đó, nó chờ 2 giây và lặp lại quá trình này.
Dưới đây là toàn bộ trang web:
<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>
Nếu nó giúp, đây là một ví dụ về json tôi gửi lại (đó là mảng này chính xác wuith hàng ngàn mục thay vì chỉ một):
[
{
mpe_name: "DBOSS-995",
request_time: "09/18/2009 11:51:06",
bin: 4,
filtered_delta: 1,
failed_delta: 1
}
]
EDIT: tôi đã chấp nhận câu trả lời cực kỳ hữu ích Toran, nhưng tôi cảm thấy tôi nên đăng một số mã bổ sung, vì removefromdom
jQuery plugin của ông có một số hạn chế:
- Nó chỉ xóa từng phần tử. Vì vậy, bạn không thể cho nó một truy vấn như `$ (" # nội dung tbody tr ")` và mong đợi nó để loại bỏ tất cả các yếu tố bạn đã chỉ định.
- Bất kỳ yếu tố nào bạn xóa cùng với phần tử phải có thuộc tính `id`. Vì vậy, nếu tôi muốn loại bỏ `tbody` của tôi, sau đó tôi phải gán một` id` vào thẻ `tbody` của tôi hoặc nếu không nó sẽ đưa ra một lỗi.
- Nó tự xóa phần tử và tất cả các phần tử của nó, vì vậy nếu bạn chỉ muốn xóa phần tử đó thì bạn sẽ phải tạo lại phần tử đó (hoặc sửa đổi plugin thành trống thay vì xóa).
Vì vậy, đây là trang của tôi ở trên được sửa đổi để sử dụng plugin của Toran. Để đơn giản, tôi không áp dụng bất kỳ lời khuyên hiệu suất chung nào offered by Peter. Dưới đây là trang mà bây giờ không có rò rỉ bộ nhớ còn:
<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>
THÊM EDIT: Tôi sẽ để lại câu hỏi của tôi không thay đổi, mặc dù nó có giá trị lưu ý rằng bộ nhớ bị rò rỉ này không có gì để làm với Ajax. Trong thực tế, đoạn code sau sẽ rò rỉ bộ nhớ chỉ giống nhau và được chỉ là một cách dễ dàng giải quyết với removefromdom
jQuery plugin Toran của:
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);
Câu hỏi ngớ ngẩn, nhưng vì nó phụ thêm vào phần thân trên mỗi lần tìm nạp, làm thế nào nó có thể sử dụng cùng một lượng bộ nhớ? –
Nó làm trống ra tbody trước khi phụ thêm vào nó. Tôi hy vọng những hàng trống sẽ bị thu gom rác, mặc dù ai đó chắc chắn sẽ cho tôi biết nếu tôi nhầm lẫn về điều này. –
Trong IE6/7/8 bạn không thể thực sự loại bỏ một phần tử DOM được tạo động mà không làm việc lạ xung quanh để null bên trongHTML (set innerHTML = "") –