javascript - 如何完全分离/销毁 MutationObserver(可能的内存泄漏)
问题描述
所以我有一个元素(我们称之为“列表”),我使用MutationObserver观察更改(attr 和 childList 添加/删除) 。这个元素有一个“切换”开关,我用它来启用/禁用元素交互和观察。
切换元素与我用来断开观察者的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)
控制台日志
/* 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...
如您所见,日志显示它每次都是不同的事件实例,但由于某种原因,即使我已经与观察者断开连接,旧的变异引用也会保留。
到目前为止我尝试过的事情。
'.list'
removedEventListener 并在每个 disconnect() 上重新添加到元素上null
'ed 和deleted
观察者,并在每个断开连接()上实例化新的观察者- 附加侦听器以切换并
toggle.parentNode.removeChild(toggle)
从 DOM 中删除元素,希望也删除对它的引用(这里没有运气),然后重新创建一个新的 DOM 切换。
如果有人能弄清楚这是怎么回事以及我如何垃圾收集/完全取消引用该观察者,我将不胜感激,因此当我切换到ON时,就好像在没有将那些以前的记录保留在内存中的情况下建立了一个新的观察者。
编辑:记录连接/断开连接消息
解决方案
推荐阅读
- bash - 脚本在 Windows 中运行,但在 Jenkins 中失败
- dart - 是否可以在 Dart 类上要求泛型类型参数?
- android - 在 Android Studio 中开发的 Flutter 项目的合法 .gitignore 是什么?
- python - Python Pandas 按一列分组
- firebase - 我应该如何在不破坏嵌套的情况下过滤 RECORD 中的列?
- sql - 确定连续和独立的 PTO 天数
- powershell - 在 Powershell 中高效处理多个 CSV
- java - android - 如果未进行搜索,则隐藏 recyclerview
- java - 使用 Spring WebClient + ConfigServer
- javascript - 我的函数说 Uncaught TypeError: $(...).reverse is not a function