如何完全分离/破坏MutationObserver(可能的内存泄漏)

时间:2019-03-16 08:36:33

标签: javascript events memory-leaks garbage-collection mutation-observers

因此,我有一个元素(我们称其为“列表”),可以使用 MutationObserver 监视更改(attr和childList添加/删除)。该元素具有一个“ toggle ”开关,该开关用于启用/禁用元素交互和观察。

toggle元素与observer.disconnect()相关联,用于断开观察者的连接,就像我不想在将其切换为“ OFF ”时进行进一步观察一样。

现在当我想进行交互并再次“观察”该元素时,问题就开始了。当我查看日志时,似乎重新连接后(observer.connect(...))。以前的突变仍保留在内存中。

我还需要适当地分离此观察器,因为我还将POST请求发送到mongodb服务器。有了这个问题,它会导致我的变异列表有些膨胀,并以更多不必要的HTTP请求来污染我的POST请求。它不包括在这篇文章中,只是提及上下文。


继续使用实际代码,请查看日志和我的应用程序的简化代码结构:

HTML

<div class="list" data-observe="false"> <!-- eventListener attached here, e.g, to ".list" -->
    <div class="list-header">
        <div class="list-toggle-wrap">
            <button class="toggle-btn">Toggle</button>
        </div>
    </div>
    <div class="list-content">
        <!-- observed elements here... -->
    </div>
</div>

JS

const watch = e => {
    if (e.target.matches('.toggle-btn')) {

        const list = e.target.closest('.list')
        const config = {
            attributeFilter: ['value', 'class'],
            attributeOldValue: true,
            childList: true,
            subtree: true,
        }

        const rng = Math.floor(Math.random() * 100)
        const randomHash = () => crypto.randomBytes(6).toString('hex')

        // logging random strings to observe if instance is the same
        console.log(randomHash())

        const callback = mutations => {

            // just logging if mutations are being detected
            console.log(`mutation detected: ${rng}`)

            mutations.forEach(mutation => {
                 // handle mutations
            }
        }

        const observer = new MutationObserver(callback)

        if (list.dataset.observe === 'true') {
            // if observing
            console.log('Observer Disconnected.')
            list.removeEventListener('click', watch)
            observer.disconnect()
            list.dataset.observe = 'false'

        } else if (list.dataset.observe === 'false') {
            // if not observing
            console.log('Observer Connected.')
            list.dataset.observe = 'true'
            observer.observe(list, config)
        }
    }
}

const list = document.querySelector('.list')
list.addEventListener('click', watch)

console.log

/* I'm generating these by clicking toggle ON and OFF without mutating
 * anything else
 * 
 * Also do note that I'm filtering uneeded mutations on my callback so
 * it doesn't show/log here, figured I want to mention that since you
 * may ask if this is just some of the actual mutation happening,
 * which is actually not the case
 */

e520c5769d34           list.controller.js:250:12
Observer Connected...  list.controller.js:462:20
mutation detected: 44  list.controller.js:254:16
21cd886b5760           list.controller.js:250:12
Observer Disconnected. list.controller.js:428:20
mutation detected: 44  list.controller.js:254:16
5781b586160c           list.controller.js:250:12
Observer Connected...  list.controller.js:462:20
mutation detected: 44  list.controller.js:254:16
mutation detected: 72  list.controller.js:254:16
29c47a6f6ece           list.controller.js:250:12
Observer Disconnected. list.controller.js:428:20
mutation detected: 44  list.controller.js:254:16
mutation detected: 72  list.controller.js:254:16
797a9dfa19b2           list.controller.js:250:12
Observer Connected...  list.controller.js:462:20
mutation detected: 44  list.controller.js:254:16
mutation detected: 72  list.controller.js:254:16
mutation detected: 52  list.controller.js:254:16
b51b16721df9           list.controller.js:250:12
Observer Disconnected. list.controller.js:428:20
mutation detected: 44  list.controller.js:254:16
mutation detected: 72  list.controller.js:254:16
mutation detected: 52  list.controller.js:254:16
145ba03997a5           list.controller.js:250:12
Observer Connected...  list.controller.js:462:20
mutation detected: 44  list.controller.js:254:16
mutation detected: 72  list.controller.js:254:16
mutation detected: 52  list.controller.js:254:16
mutation detected: 15  list.controller.js:254:16
8acb6fabd173           list.controller.js:250:12
Observer Disconnected. list.controller.js:428:20
mutation detected: 44  list.controller.js:254:16
mutation detected: 72  list.controller.js:254:16
mutation detected: 52  list.controller.js:254:16
mutation detected: 15  list.controller.js:254:16
1a9f20e41cb5           list.controller.js:250:12
Observer Connected...  list.controller.js:462:20
mutation detected: 44  list.controller.js:254:16
mutation detected: 72  list.controller.js:254:16
mutation detected: 52  list.controller.js:254:16
mutation detected: 15  list.controller.js:254:16
mutation detected: 55  list.controller.js:254:16
f4393ece6540           list.controller.js:250:12
Observer Disconnected. list.controller.js:428:20
mutation detected: 44  list.controller.js:254:16
mutation detected: 72  list.controller.js:254:16
mutation detected: 52  list.controller.js:254:16
mutation detected: 15  list.controller.js:254:16
mutation detected: 55  list.controller.js:254:16
762116b899da           list.controller.js:250:12
Observer Connected...  list.controller.js:462:20
mutation detected: 44  list.controller.js:254:16
mutation detected: 72  list.controller.js:254:16
mutation detected: 52  list.controller.js:254:16
mutation detected: 15  list.controller.js:254:16
mutation detected: 55  list.controller.js:254:16
mutation detected: 6   list.controller.js:254:16
and so on...

如您所见,该日志显示每次由于某种原因而每次BUT时,它都是一个不同的事件实例,即使我已经与观察者断开连接,旧的变异引用也得以保留。


到目前为止我已经尝试过的事情。

  • removedEventListener并在每个'.list'元素上重新添加 Disconnect()
  • nulldeleted的观察者进行实例化 每个disconnect()上都有新的观察者
  • 附加的侦听器以切换和 toggle.parentNode.removeChild(toggle)从中删除元素 DOM,希望也删除它的引用(这里没有运气),然后在此之后重新创建一个新的DOM切换。

如果有人能弄清楚情况如何,以及如何对这个观察者进行垃圾回收/完全取消引用,我将不胜感激,因此当我切换 ON 时,就好像是在没有观察员的情况下创建了一个新观察者这些先前的记录将保留在内存中。

编辑:记录连接/断开连接消息

0 个答案:

没有答案