Как полностью отключить / уничтожить MutationObserver (возможная утечка памяти) - PullRequest
0 голосов
/ 16 марта 2019

Итак, у меня есть элемент (назовем этот «Список»), который я наблюдаю за изменениями (добавление / удаление attr и childList), используя MutationObserver . Этот элемент имеет переключатель « toggle », который я использую для включения / отключения взаимодействия и наблюдения за элементами.

Элемент переключателя связан с наблюдаем.disconnect (), который я использую для отключения наблюдателя, так же как я не хочу дальнейших наблюдений при переключении " OFF ".

Теперь проблема начинается, когда я хочу взаимодействовать и снова "наблюдать" за этим элементом . Пока я смотрю логи, кажется, что после повторного подключения (наблюдатель.коннект (...)). Предыдущие мутации все еще хранятся в памяти.

Мне нужно правильно отключить этого наблюдателя, поскольку я также отправляю запрос POST на сервер mongodb. Из-за этой проблемы в моем списке мутаций возникает нечто вроде раздувания И загрязняет мой запрос POST более ненужными HTTP-запросами. Он не включен в этот пост, но только для контекста.


Переходя к реальному коду, просмотрите журналы и упрощенную структуру кода моего приложения:

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...

Как вы можете видеть, журнал показывает, что каждый раз это новый экземпляр события, НО по какой-то причине старые ссылки на мутации сохраняются, даже если я уже отключился от наблюдателя.


То, что я пробовал до сих пор.

  • removeEventListener и повторно добавляется в элемент '.list' на каждом отсоединить ()
  • null 'ed и deleted наблюдатель и экземпляр новый наблюдатель при каждом отключении ()
  • прикрепленный слушатель к переключателю и toggle.parentNode.removeChild(toggle) чтобы удалить элемент из DOM, мы надеемся, что удаляем ссылки на него (не повезло), а затем воссоздадим новый переключатель DOM после.

Был бы очень признателен, если бы кто-нибудь смог понять, как это происходит и как я могу собрать / полностью разыменовать этого наблюдателя, поэтому, когда я переключаю ON , это будет, как если бы установил новый наблюдатель без этих предыдущие записи сохраняются в памяти.

Редактировать: протокол подключения / отключения сообщения

...