IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Fuite mémoire dans ce composant vuejs


Sujet :

JavaScript

  1. #1
    Membre actif Avatar de Gobble
    Homme Profil pro
    Intégrateur Web
    Inscrit en
    Octobre 2014
    Messages
    100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Intégrateur Web
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Octobre 2014
    Messages : 100
    Points : 222
    Points
    222
    Par défaut Fuite mémoire dans ce composant vuejs
    Bonjour,

    Voici un composant vuejs qui affiche une modal avec un gif quand on tape le konami code dans le navigateur (haut haut bas bas gauche droite gauche droite BA ENTER)

    Il y a une fuite mémoire dans ce code, quelqu'un pourrait m'éclairer ? Je crois que c'est lié au getElementById dans la méthode handleKeydown. Mais j'aimerais bien une explication éclairée.

    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    <template>
      <div id="myModal" class="modal">
        <div class="modal-content">
          <span class="close" @click="closeModal">&times;</span>
          <img alt="Hey" src="../assets/sold.gif">
          <p>{{ message }}</p>
        </div>
      </div>
    </template>
     
    <script>
    export default {
      name: "KonamiCode",
      data() {
        return {
          showGif: false,
          konamiCode: [38, 38, 40, 40, 37, 39, 37, 39, 66, 65, 13],
          enteredCode: [],
          modal:null,
          message: "Bravo pour avoir tapé le Konami Code Secret !"
        };
      },
      methods: {
        closeModal(){
          this.modal.style.display = "none";
        },
        handleKeydown(event) {
          this.enteredCode.push(event.keyCode);
          if (this.enteredCode.toString().indexOf(this.konamiCode) >= 0) {
            console.log("Konami Code entered!");
            this.showGif = true;
            this.modal = document.getElementById("myModal");
            this.modal.style.display = "block";
            this.enteredCode = [];
          }
        }
      },
      mounted() {
        window.addEventListener("keydown", this.handleKeydown);
      },
      beforeDestroy() {
        window.removeEventListener("keydown", this.handleKeydown);
      }
    }
    </script>
     
    <style scoped>
    img{
      margin:auto;
    }
    </style>

    En vous remerciant

  2. #2
    Membre actif
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2009
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Juillet 2009
    Messages : 132
    Points : 283
    Points
    283
    Par défaut
    Bonjour,

    Qu'est-ce qui te fais dire qu'il y a une fuite mémoire ?
    Éventuellement il pourrait y avoir un problème avec `enteredCode` si Vue garde des références sur les items sachant que c'est un objet réactif.

    D'ailleurs il n'y a pas besoin que `enteredCode` soit réactif ici. Il est préférable dans ce cas de le sortir de `data` et l'initialiser dans le hook `created` :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    created() {
      this.enteredCode = [];
    }
    Pareil pour les autres propriétés dont le rendu du composant ne dépend pas.

  3. #3
    Membre actif Avatar de Gobble
    Homme Profil pro
    Intégrateur Web
    Inscrit en
    Octobre 2014
    Messages
    100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Intégrateur Web
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Octobre 2014
    Messages : 100
    Points : 222
    Points
    222
    Par défaut
    Qu'est-ce qui te fais dire qu'il y a une fuite mémoire ?
    Bonjour JérémieL,

    J'ai eu ce retour de fuite mémoire sur ce composant en livrant un mini projet vuejs pour un emploi.


    D'ailleurs il n'y a pas besoin que `enteredCode` soit réactif ici. Il est préférable dans ce cas de le sortir de `data` et l'initialiser dans le hook `created` :
    Woops, bien vu,j'ai toujours pris pour habitude de définir mes données même non réactives dans le data du composant.

  4. #4
    Membre actif
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2009
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Juillet 2009
    Messages : 132
    Points : 283
    Points
    283
    Par défaut
    Citation Envoyé par Gobble Voir le message
    Bonjour JérémieL,
    J'ai eu ce retour de fuite mémoire sur ce composant en livrant un mini projet vuejs pour un emploi.
    Sans davantage d'explication ?
    Si c'est dans le cadre d'un test technique, ce serait logique que le recruteur s'attende à une fuite sur le listener, mais là il est bien supprimé dans le `beforeDestroy` donc c'est étonnant.

  5. #5
    Membre actif Avatar de Gobble
    Homme Profil pro
    Intégrateur Web
    Inscrit en
    Octobre 2014
    Messages
    100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Intégrateur Web
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Octobre 2014
    Messages : 100
    Points : 222
    Points
    222
    Par défaut
    Et bien dans la liste des point positifs il est bien mentionné la destruction du event listeners. Ensuite dans les points négatifs "Fuite de mémoire dans le konami code". mais je n'ai pas pu avoir + de détails.

  6. #6
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 395
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 395
    Points : 15 756
    Points
    15 756
    Par défaut
    tant que le konami code n'est pas détecté, le tableau enteredCode stocke toutes les touches. est ce que c'est ça qui serait détecté comme une fuite mémoire théorique ?
    je précise "théorique" parce que dans la pratique, je pense qu'il faudrait écrire un roman pendant plusieurs heures avant de commencer à saturer la mémoire avec ça.

  7. #7
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 098
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 098
    Points : 44 675
    Points
    44 675
    Par défaut
    Bonjour,
    en regardant rapidement tu gardes une référence avec ton
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.modal = document.getElementById("myModal");
    donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    beforeDestroy() {
      this.modal = null;
      window.removeEventListener("keydown", this.handleKeydown);
    }

  8. #8
    Membre actif
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2009
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Juillet 2009
    Messages : 132
    Points : 283
    Points
    283
    Par défaut
    Non NoSmoking, pas besoin car lors de la destruction du composant, la référence est automatiquement supprimée.

  9. #9
    Membre actif Avatar de Gobble
    Homme Profil pro
    Intégrateur Web
    Inscrit en
    Octobre 2014
    Messages
    100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Intégrateur Web
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Octobre 2014
    Messages : 100
    Points : 222
    Points
    222
    Par défaut
    Donc il y a effectivement une vérification à faire sur la variable modal pour éviter de réassigner plusieurs fois l'élément DOM à cette modal.

    Et ensuite, il y a effectivement un problème avec la variable enteredCode, je vidais la variable uniquement si le konami code était détecté.
    Donc il faut rajouter une condition qui vide la variable récupérant les touches si la taille dépasse le konami code

    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    <template>
      <div id="myModal" class="modal">
        <div class="modal-content">
          <span class="close" @click="closeModal">&times;</span>
          <img alt="Hey" src="../assets/sold.gif">
          <p>{{ message }}</p>
        </div>
      </div>
    </template>
     
    <script>
    export default {
      name: "KonamiCode",
      data() {
        return {
          konamiCode: [38, 38, 40, 40, 37, 39, 37, 39, 66, 65, 13],
          enteredCode: [],
          modal:null,
          message: "Bravo pour avoir tapé le Konami Code Secret !"
        };
      },
      methods: {
        closeModal(){
          if (this.modal) {
            this.modal.style.display = "none";
          }
        },
        handleKeydown(event) {
          this.enteredCode.push(event.keyCode);
          if (this.enteredCode.toString().indexOf(this.konamiCode) >= 0) {
            console.log("Konami Code entered!");
           
            if (this.modal) {
              this.modal.style.display = "block";
            }
            this.enteredCode = [];
          } else if (this.enteredCode.length > this.konamiCode.length) {
            this.enteredCode = [];
          }
        }
      },
      mounted() {
        this.modal = document.getElementById("myModal");
        window.addEventListener("keydown", this.handleKeydown);
      },
      beforeDestroy() {
        window.removeEventListener("keydown", this.handleKeydown);
      }
    }
    </script>
     
    <style scoped>
    img{
      margin:auto;
    }
    </style>

    Après concernant la remarque de noSmoking de réinitialiser à null, dans la documentation de vuejs sur les fuites mémoires ils font cela, mais peut être que c'est fait automatiquement au destroy du composant ?

  10. #10
    Membre actif Avatar de Gobble
    Homme Profil pro
    Intégrateur Web
    Inscrit en
    Octobre 2014
    Messages
    100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Intégrateur Web
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Octobre 2014
    Messages : 100
    Points : 222
    Points
    222
    Par défaut
    Bon du coup je me suis documenté et vuejs ne fait pas automatiquement le vidage, les références ne sont pas supprimées, elles peuvent persister en mémoire du coup il est bon de le faire manuellement dans chaque composant
    d'ailleurs dans vuejs 3 ce n'est plus beforeDestroy mais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    beforeUnmount() {
      this.variable = null;
    }
    Bon à savoir pour éviter un prochain fail pour un poste de développeur front-end

Discussions similaires

  1. [OCI] Fuite mémoire dans libclntsh
    Par Adil BE dans le forum Interfaces de programmation
    Réponses: 8
    Dernier message: 08/09/2009, 14h52
  2. Fuite mémoire dans une appli dev avec vc++6
    Par devconf77 dans le forum Windows
    Réponses: 1
    Dernier message: 26/08/2008, 08h58
  3. fuite mémoire dans le JSP editor
    Par ChristopheH dans le forum Eclipse Java
    Réponses: 0
    Dernier message: 18/04/2008, 17h20
  4. fuite mémoire dans un processus
    Par ryadh.naouar dans le forum POSIX
    Réponses: 4
    Dernier message: 09/05/2007, 11h53
  5. Réponses: 19
    Dernier message: 04/10/2006, 16h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo