[英]Major JavaScript memory leak
大家! 我正在處理某種事件日歷,並且將jQuery用於前端,將PHP用於后端。 我已經用PHP創建了所有日歷數據,並以JSON編碼發送到了客戶端。
考慮以下代碼(簡化):
jQuery(document).ready(function($) {
// property which contains calendar object
this.Calendar;
// get calendar object
show_month();
/* Assign a click event to the next month button */
$('#cal_month .next span').live('click', function() {
var month = $(this).attr('id');
var year = $(this).attr('class');
show_month(month, year);
});
function show_month(month, year) {
// delete pointers to the current month object
window.Calendar = undefined;
// get new month object
window.Calendar = get_month(month, year);
/* doing some stuff with this object here, like output to the
document etc., no event bindings */
}
function get_month(month, year) {
var calendar;
$.ajax({
type: 'GET',
dataType: 'json',
async: false,
timeout: 100,
url: '../some_url.php?month='+month+'&year='+year,
success: function(result) { calendar = result; }
});
return calendar;
}
var counter = 0;
while (counter != 1000) {
$('#cal_month .next span').trigger('click');
counter ++;
}
});
手動切換數月以及進行循環會導致巨大的內存泄漏。 我已經在這里以及通常在互聯網上閱讀了大量有關內存泄漏,js關閉等的信息,但我想我仍然有些誤解。 我很高興對我的代碼中的錯誤有一些想法。
更新
我正在觀察任務管理器中的firefox.exe(其他瀏覽器有同樣的問題),正在測量內存使用情況。 即使從頁面導航,記憶也不免費。 一段時間后,由於使用600+ Mb,它會導致性能下降。
我還寫了一個循環來切換月份(上面添加了代碼)。
更新2
我使用global的原因是,在我的事件日歷中,我還具有周和日視圖,因此我希望活動的月份對象可用於處理這兩個視圖的功能,並且僅當用戶使用時銷毀它並獲得新的視圖切換月份。 我的問題恰恰是全局變量的用法。 解決了那個問題,現在試圖弄清楚如何使對象保持可用狀態,直到用戶明確切換月份為止。
順便說一句,我創建了一個while循環,僅用於基准測試,它與我的實際代碼無關。
我很好奇您為什么會認為存在內存泄漏問題。 我看到另外兩個與內存無關的大問題,但也許更重要。
第一個問題是同步服務器調用。 你應該在主從來沒有使用同步調用,因為它鎖定瀏覽器,同時請求正在進行中。 編輯 :在該循環中執行1000次將最多鎖定瀏覽器1000 * 100毫秒,這會引起一些用戶體驗問題。
第二個是全局Calendar對象。 除了依靠混亂的全局狀態之外,您還無法做一些簡單的事情,例如在同一頁面上有兩個日歷。
下面的代碼修復了這兩個問題。
jQuery(document).ready(function($) {
$('#cal_month .next span').live('click', function() {
var month = $(this).attr('id');
var year = $(this).attr('class');
generate_calendar(month, year);
});
generate_calendar();
function calendar_fetch_complete(result) {
var calendar = result;
/* doing some stuff with this object here, like output to the
document etc.*/
}
function generate_calendar(_month, _year) {
var month = _month || (new Date().getMonth() + 1),
year = _year || (new Date().getYear() + 1900);
$.ajax({
type: 'GET',
dataType: 'json',
url: '../some_url.php?month='+month+'&year='+year,
success: calendar_fetch_complete
});
}
});
我建議使用諸如http://www.dynatrace.com/en/之類的工具,這些工具有時會很有幫助。
請查看John Resig自己的這篇文章http://ejohn.org/blog/deep-tracing-of-internet-explorer/ 。
嘗試以下螢火蟲把戲:建議您再嘗試一件事。 簡單的螢火蟲把戲。 當您不在UI控件上使用/鼠標操作時,只需單擊Firebug的配置文件按鈕。 看看有多少個函數正在發生調用,看看是否有些東西是奇數的並且花費了很長時間。 它是一個很好的簡單技巧,但可以幫助解決此類問題... :)
var counter = 0;
while (counter != 1000) {
$('#cal_month .next span').trigger('click');
counter ++;
}
什么? 根據此代碼,您將觸發多個span元素1000次,並為這些元素中的每一個請求同步JSON 1000次,這將重寫單個全局變量。 這不是內存“泄漏”,而是精疲力盡。
我建議將您的代碼重構為包括異步請求,並取出while循環。
您說存在內存泄漏,但是如何確定呢?
可能是您只是在查看瀏覽器進程的內存使用情況。 瀏覽器對內存所做的任何操作都不一定與您在javascript中所做的事情有關。 可能是javascript引擎沒有釋放它認為會再次使用的內存空間-無論您當前是否正在使用它。
請找到正確的工具進行分析和/或提供更多有關為什么您認為內存泄漏的信息。
while(count!= 1000){$('#cal_month .next span')。trigger('click'); 計數器++; }
看起來您正在將1000個觸發器分配給某個對象-您不能處理來自父對象的任何點擊嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.