避免微任务去抖动器上的内存泄漏

时间:2017-01-04 11:52:20

标签: javascript memory-leaks

我试图修复这个基于微任务的去抖动器的内存泄漏:

function microtaskDebounce(fn) {
    let scheduled = false;
    let i = 0;
    let elem = document.createElement('span');

    // MutationObserver provides a mechanism for scheduling microtasks, which
    // are scheduled *before* the next task. This gives us a way to debounce
    // a function but ensure it's called *before* the next paint.
    const observer = new MutationObserver(() => {
        fn();
        scheduled = false;
    });

    observer.observe(elem, { childList: true });

    return () => {
        if (!scheduled) {
            scheduled = true;
            elem.textContent = `${i}`;
            i = i + 1; // don't use compund (+=) because it doesn't get optimized in V8
        }
    };
}

// usage example
const fn = microtaskDebounce(someFunction.bind(this));
for (let i = 0; i < 1000; i++) {
  fn();
}

这是基于setTimeout的去抖动的时间轴: enter image description here

相反,这是微任务辩手的时间轴: enter image description here

正如你所看到的,使用microtask debouncer,我用来检测重绘的DOM元素似乎泄漏并污染了内存。

我该如何解决?

供参考,这是我使用此功能的库: https://github.com/FezVrasta/popper.js/blob/v1-dev/src/popper/index.js#L132

更新

elem.textContent替换为elem.setAttribute('x-index', i),并使用observer.observe(elem, { attributes: true });进行观察以修复泄漏。
我仍然不明白为什么innerText导致内存泄漏!

我在此CodePen中重现了这个问题: http://codepen.io/FezVrasta/pen/pRomWL

debug mode中打开它,让时间轴记录页面加载,你会在内存中看到数千个节点。

0 个答案:

没有答案