web-dev-qa-db-fra.com

Quelle est la bonne façon de détruire une instance de carte?

J'ai récemment développé une application mobile html5. L'application était une page unique où les événements de changement de hachage de navigation remplaçaient l'intégralité du DOM. Une section de l'application était une carte Google Map utilisant API v3. Avant que le div de la carte ne soit supprimé du DOM, je souhaite supprimer tout gestionnaire d'événement/écouteur et libérer autant de mémoire que possible, car l'utilisateur ne pourra plus jamais revenir à cette section.

Quel est le meilleur moyen de détruire une instance de carte?

83

Le réponse officielle est que vous ne le faites pas. Les instances de carte dans une application à une seule page doivent être réutilisées et non détruites puis recréées.

Pour certaines applications à une seule page, cela peut impliquer une nouvelle architecture de la solution, de sorte qu'une fois créée, une carte peut être masquée ou déconnectée du DOM, mais elle n'est jamais détruite ni recréée.

25
Chad Killingsworth

J'ajoute une deuxième réponse à cette question, car je ne veux pas supprimer les allers et retours que nous avions par le biais des commentaires de suivi de ma réponse précédente.

Mais je suis récemment tombé sur des informations qui répondent directement à votre question et je voulais donc les partager. Je ne sais pas si vous êtes au courant de cela, mais lors du Google Maps API Heures de bureau du 9 mai 2012 Vidéo , Chris Broadfoot et Luke Mahe de Google ont discuté de cette question de stackoverflow. Si vous définissez la lecture vidéo sur 12:50, c'est la section où ils discutent de votre question.

Ils reconnaissent essentiellement qu'il s'agit d'un bogue, mais ajoutent qu'ils ne prennent pas en charge les cas d'utilisation impliquant la création/la destruction d'instances de carte successives. Ils recommandent vivement de créer une seule instance de la carte et de la réutiliser dans n'importe quel scénario de ce type. Ils parlent également de la définition de la carte sur null et de la suppression explicite des écouteurs d'événements. Vous avez exprimé des préoccupations à propos des écouteurs d'événements. Je pensais que le fait de définir la carte sur null suffirait, mais il semble que vos préoccupations soient valides, car elles font spécifiquement référence aux écouteurs d'événements. Ils ont également recommandé de supprimer complètement la DIV qui contient la carte.

Quoi qu'il en soit, je voulais simplement transmettre ceci et m'assurer qu'il est inclus dans la discussion sur la superposition et espérer que cela vous aidera, à vous-même et aux autres.

45
Sean Mickey

Étant donné qu'apparemment, vous ne pouvez pas vraiment détruire les instances de carte, un moyen de réduire ce problème si 

  • vous devez afficher plusieurs cartes à la fois sur un site Web
  • le nombre de cartes peut changer avec l'interaction de l'utilisateur
  • les cartes doivent être masquées et rediffusées avec d'autres composants (c'est-à-dire qu'elles n'apparaissent pas à une position fixe dans le DOM)

conserve un pool d'instances de mappage . Le pool conserve une trace des instances utilisées et, lorsqu'une nouvelle instance lui est demandée, il vérifie si l'une des instances de mappe disponibles est libre: si c'est le cas, elle renverra une instance existante si ce n’est pas le cas, il créera une nouvelle instance de carte et la retournera en l’ajoutant au pool. Ainsi, vous n'aurez qu'un nombre maximal d'instances égal au nombre maximal de cartes que vous affichez simultanément à l'écran . J'utilise ce code (il nécessite jQuery):

var mapInstancesPool = {
 pool: [],
 used: 0,
 getInstance: function(options){
    if(mapInstancesPool.used >= mapInstancesPool.pool.length){
        mapInstancesPool.used++;
        mapInstancesPool.pool.Push (mapInstancesPool.createNewInstance(options));
    } else { 
        mapInstancesPool.used++;
    }
    return mapInstancesPool.pool[mapInstancesPool.used-1];
 },
 reset: function(){
    mapInstancesPool.used = 0;
 },
 createNewInstance: function(options){
    var div = $("<div></div>").addClass("myDivClassHereForStyling");
    var map =   new google.maps.Map(div[0], options);
    return {
        map: map,
        div: div
    }
 }
}

Vous lui transmettez les options de la carte de départ (conformément au deuxième argument du constructeur de google.maps.Map) et renvoie à la fois l'instance de la carte (sur laquelle vous pouvez appeler des fonctions appartenant à google.maps.Map) et le conteneur, qui vous pouvez styler en utilisant la classe "myDivClassHereForStyling", et vous pouvez ajouter un dinamically au DOM . Si vous devez réinitialiser le système, vous pouvez utiliser mapInstancesPool.reset (). Il remettra le compteur à 0 tout en conservant toutes les instances existantes dans le pool pour pouvoir les réutiliser ..__ Dans mon application, je devais supprimer toutes les cartes en même temps et créer un nouvel ensemble de cartes. exemple: votre kilométrage peut varier ... Pour supprimer les cartes de l'écran, j'utilise le détachement de jQuery, qui ne détruit pas le conteneur de la carte.

En utilisant ce système et en utilisant

google.maps.event.clearInstanceListeners(window);
google.maps.event.clearInstanceListeners(document);

et courir

google.maps.event.clearInstanceListeners(divReference[0]);
divReference.detach()

(où divReference est l’objet jQuery de la div retourné par le pool d’instances). les uns.

11
Paolo Mioni

J'aurais suggéré de supprimer le contenu de la carte div et d'utiliser delete sur la variable contenant la référence à la carte, et probablement explicitement deleteing les écouteurs d'événements.

Il y a un bug reconnu , cependant, et cela risque de ne pas fonctionner.

5
Andrew Leach

Comme google ne fournit pas gunload () pour api v3, mieux utiliser iframe en html et assigner map.html comme source à cette iframe après utilisation, faire src comme null. Cela va certainement libérer la mémoire consommée par la carte.

2
kumar

Lorsque vous supprimez la div, le panneau d’affichage est supprimé et la carte disparaît. Pour supprimer l'instance de carte, assurez-vous que votre référence à la carte est définie sur null et que toutes les références à d'autres parties de la carte sont définies à null. À ce stade, la récupération de mémoire JavaScript se chargera du nettoyage, comme indiqué dans: Comment fonctionne la récupération de place en JavaScript? .

1
Sean Mickey

Je suppose que vous parlez de addEventListener. Lorsque vous supprimez les éléments DOM, certains navigateurs génèrent ces événements sans les supprimer. C'est pourquoi jQuery fait plusieurs choses lors de la suppression d'un élément:

  • Il supprime les événements quand il peut utiliser removeEventListener. Cela signifie qu'il conserve un tableau avec les écouteurs d'événements ajoutés à cet élément.
  • Il supprime les attributs relatifs aux événements (onclick, onblur, etc.) à l'aide de delete sur l'élément DOM lorsque addEventListener n'est pas disponible (néanmoins, il possède un tableau dans lequel sont stockés les événements ajoutés).
  • Il définit l'élément sur null pour éviter IE 6/7/8 des fuites de mémoire.
  • Il supprime ensuite l'élément.
0