簡體   English   中英

如何追蹤事件監聽器的添加位置?

[英]How do I track down where event listener is getting added?

我有一個相當好的javascript(有react / redux但沒有jquery)代碼庫用於我正在構建的webapp,我注意到當我在UI中反復打開和關閉某個面板時,監聽器的數量根據Chrome的性能時間表不斷增加。

該圖如下所示: 時間線圖

我已經允許chrome的性能監視器運行一兩分鍾,頁面處於空閑狀態(在打開/關閉面板之后),希望聽眾可能會收集垃圾,但事實並非如此。 我在這個過程中切換到其他選項卡,也希望聽眾在選項卡背景時收集垃圾,但不幸的是,他們不會。

因此,我懷疑有些聽眾正在注冊,但從未注冊過。

這引出了兩個主要問題:

  1. 我的假設是聽眾是否會得到補充並且從未被束縛似乎是明智的,或者我可以采取更多措施來證實這種懷疑?
  2. 假設我的懷疑是正確的,我怎樣才能最好地追蹤添加事件監聽器的代碼? 我已經嘗試過以下方法:
    • 查看負責打開相關面板的代碼,查看它添加任何偵聽器的位置,並注釋掉這些部分以查看性能圖中是否有任何更改。 沒有變化。
    • 像這樣重寫addEventListener原型:

var f = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function(type, fn, capture) {
    this.f = f;
    this.f(type, fn, capture);
    console.trace("Added event listener on" + type);
}

即使在這樣做之后,然后注釋掉導致執行此console.trace的所有代碼部分(參見#1),以便在打開/關閉面板時不再打印console.trace,我注意到聽眾的增加相同在性能圖表中。 其他一些因素導致聽眾增加。 我知道還有其他方法可以添加監聽器,但是我不清楚如何攔截所有這些可能性或導致它們以這樣的方式登錄Chrome的調試器,以便我可以告訴哪些代碼負責添加它們。

編輯 : - 根據評論中cowbert的建議,我看了一下這個頁面: https//developers.google.com/web/tools/chrome-devtools/console/events

然后我做了以下功能:

function printListenerCount() {
    var eles = document.getElementsByTagName("*");
    var numListeners = 0;
    for (idx in eles) { let listeners = getEventListeners(eles[idx]);
        for(eIdx in listeners)
        {
            numListeners += listeners[eIdx].length;
        }
        console.log("ele", eles[idx], "listeners", getEventListeners(eles[idx]));
    }
    console.log("numListeners", numListeners)
}

我打開/關閉面板多次后執行此功能,但不幸的是“numListeners”數字沒有改變。 如果numListeners數字發生了變化,我可以在打開/關閉面板之前/之后對結果進行區分,以發現哪個元素有額外的事件監聽器注冊到它,但不幸的是numListeners沒有改變。

https://developers.google.com/web/tools/chrome-devtools/console/events上還介紹了monitorEvents()API,但函數調用要求您指定要監視的DOM元素。 在這種情況下,我不確定哪個DOM元素有額外的偵聽器,所以我不確定monitorEvents()調用將如何真正幫助我。 我可以將它附加到所有DOM元素,類似於我上面編寫的printListenerCount函數,但我認為我遇到了類似的問題,我遇到了printListenerCount() - 無論出於何種原因,它都不能解決有問題的聽眾。

其他說明:這是一個有點復雜的反應(基於預制,技術)的應用程序。 與大多數基於reactjs的應用程序一樣,組件可以即時安裝/卸載(插入DOM或從DOM中刪除)。 我發現這使得跟蹤“雜散事件處理程序注冊”這樣有點棘手。 所以我真正希望的是一些關於如何在諸如此類的大型/復雜項目中追蹤“Stray事件處理程序”的一般調試建議。 作為C程序員,我會打開gdb並在所有可能導致性能圖中“偵聽器”編號增加的內容上設置斷點。 我不確定在javascript世界中是否有類似的東西,即使它存在,我也不知道該怎么做。 任何建議將不勝感激!

謝謝大家的評論。 我最終搞清楚了。

從我的OP:

  1. 我的假設是聽眾是否會得到補充並且從未被束縛似乎是明智的,或者我可以采取更多措施來證實這種懷疑?

事實證明,這個問題的答案是:假設是不明智的。 聽眾根本沒有機會收集垃圾。 這可能比你想象的要花費更多的時間。

以下是我弄清楚的方法:我沒有意識到,在錄制性能時間線時,可以通過單擊“性能”選項卡中的垃圾桶圖標(用於啟動時間線錄制的相同選項卡)強制進行垃圾收集。 通過在UI面板重復關閉/打開后單擊此圖標,額外的聽眾完全消失了。 圖表現在看起來像這樣,逢低是我點擊垃圾桶圖標的時刻: 使用手動GC的性能時間表

顯然,像我在OP中提到的那樣,選擇標簽並等待幾分鍾根本就沒有足夠的時間來自行進行垃圾收集; 這需要更多的時間。

當我寫OP時,我沒有意識到用垃圾桶圖標手動收集垃圾的能力......我強烈建議在進行任何瘋狂的追逐之前使用它,以尋找可能最初看起來像性能問題的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM