Cette semaine, nous avons été confrontés à un problème particulier avec AngularJs.
Le navigateur affichait +500Mo de charge mémoire sur notre solution AngularJs, ce qui est bien trop avec un seul onglet.
En réalité, en observant les statistiques du nombre de watchers présents (avec ng-stat ou AngularJs Batarang) dans les différentes pages, nous avons découvert une fuite mémoire.
Chaque fois que nous cliquions sur un produit, 52 watchers s’ajoutaient aux déjà présents. Même comportement si nous revenions sur un produit sélectionné auparavant.
En réalité, la sélection d’un produit provoque un appel au serveur afin de récupérer le template destiné à être intégré dans un contrôle comprenant code html et directives éléments ou attributs AngularJs. Ce code sera donc interprété par le compile d’AngularJs.
Voici le code à ne pas faire !
this.displayP = function (data) { var parentElement = angular.element(‘#current_product’); var element = angular.element(data); $compile(element)($scope); if (parentElement.has(« li »).length) { // Remove the last product added to load the new One parentElement.empty(); } parentElement.append(element); element.find(« .text-box »).trigger(« change »); |
this.displayP = function (data) {
var parentElement = angular.element(‘#current_product’);
if (parentElement.has(« li »).length) {
// Remove last product added to load the new one
if (productInstance.childPScope != null)
productInstance.childPScope.$destroy();
parentElement.empty();
}
var element = angular.element(data);
var compiledDirectives = $compile(element);
productInstance.childPScope = $scope.$new(false);
compiledDirectives(productInstance.childPScope);
parentElement.append(element);
element.find(« .text-box »).trigger(« change »);
|
Finalement, l’instance détruite permet de supprimer les watchers inutiles et irrecupérables.
D’autres articles sur les performances dans AngularJs arriveront par la suite.
Nicolas DENIS