Maison  >  Article  >  interface Web  >  Testez que chaque MutationObserver est déconnecté pour éviter les fuites de mémoire

Testez que chaque MutationObserver est déconnecté pour éviter les fuites de mémoire

WBOY
WBOYoriginal
2024-08-22 22:34:02854parcourir

Test that every MutationObserver is disconnected to avoid memory leaks

MutationObserver est un mécanisme utile pour surveiller les changements dans le DOM et y répondre.

L'interface MutationObserver offre la possibilité de surveiller les modifications apportées à l'arborescence DOM.

Voici un exemple qui surveille un changement de classe thématique.

    function setUpThemeClassObservers() {
        const observer = new MutationObserver(() => {
            const themeClass = this.getThemeClass();
            this.fireStylesChangedEvent('themeChanged');
        });

        observer.observe(this.eGridDiv, {
            attributes: true,
            attributeFilter: ['class'],
        });

        // we must disconnect otherwise "this" will not be GC'd
        // causing a memory leak
        return () => observer.disconnect();
    }

Cependant, si vous oubliez de vous déconnecter, vous pourriez vous exposer à des fuites de mémoire en fonction de ce qui est accédé à partir des fonctions MutationObserver.

Ne serait-il pas génial d'avoir un test qui puisse valider que nous déconnectons nos observateurs ?

Validation automatique du code

Il s'avère qu'il est possible de valider que chaque MutationObserver qui observe le DOM est également déconnecté. (Vous aurez peut-être besoin de plus d'un test si vous devez exercer différents chemins de code afin de configurer les MutationObservers)

L'idée est de simuler le MutationObserver global avec des sous-simulations pour ses méthodes d'observation et de déconnexion. Avant que la simulation ne soit renvoyée, nous l'enregistrons dans un tableau afin de pouvoir valider toutes les instances à la fin du test.

describe('Mutation Observers Disconnected', () => {

    let originalMutationObserver: typeof MutationObserver;

    const allMockedObservers: any = [];
    const mutationObserverMock = jest.fn<MutationObserver, [MutationCallback]>().mockImplementation(() => {
        const mock = {
            observe: jest.fn(),
            disconnect: jest.fn(),
            takeRecords: jest.fn(),
        };
        allMockedObservers.push(mock);
        return mock;
    });

    beforeEach(() => {
        // Ensure we can restore the real MutationObserver after the test
        originalMutationObserver = global.MutationObserver;
        global.MutationObserver = mutationObserverMock;
    });

    afterEach(() => {
        global.MutationObserver = originalMutationObserver;
    });

    test('observer always disconnected after destroy', async () => {
        const api = createGrid();
        // Perform some actions if required to exercise the code paths
        api.destroy();

        expect(allMockedObservers.length).toBeGreaterThan(0);
        for (const mock of allMockedObservers) {
            expect(mock.observe).toHaveBeenCalled();
            expect(mock.disconnect).toHaveBeenCalled();
        }
    });
});

Nous pouvons ainsi valider que chaque MutationObserver, configuré lors du test, est également déconnecté à la fin du test.


Stephen Cooper - Développeur senior chez AG Grid
Suivez-moi sur X @ScooperDev

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn