2014-12-14 13 views
15

Sto usando questo file html semplice da riprodurre una perdita di memoria che ho trovato:Perdite di memoria direttive angolari?

<!doctype html> 
<html> 
    <head> 
     <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular.min.js"></script> 
     <script> 
      var app = angular.module('testApp', []); 

      app.directive('directive1', function() { 
       return { 
        template: '<div directive2></div>', 
        scope: true 
       }; 
      }); 

      app.directive('directive2', function() { 
       function LeakObject() {} 

       function Foo() { 
        this.bar = function($scope) { 
          $scope.nottheredude; 
        }; 
       } 

       return { 
        scope: true, 
        link: function($scope) { 
          $scope.memoryThatLeaks = new LeakObject(); 

          new Foo().bar({}); 
          new Foo().bar($scope); 
        } 
       }; 
      }); 
     </script> 
    </head> 
    <body ng-app="testApp"> 
     <button ng-click="show = !show">Toggle</button> 
     <div ng-if="show">The directive <div directive1></div></div> 
     <div ng-if="!show">Nothing</div> 
    </body> 
</html> 

Ho una direttiva che crea solo un nuovo ambito e ha un altro direttiva nel suo modello.

L'altra direttiva fa qualcosa di un po 'strano (ho cercato di limitare il problema a ciò che sta causando la perdita e questo è il codice più breve che ho trovato che riproduce il problema).

Nel mio html principale, non faccio altro che passare da nulla a directive1 con un semplice ng-if.

Si noti che directive2 crea anche un nuovo oggetto su $scope chiamato LeakObject. Prevedo che questo oggetto sia garbage collection quando riattivo il nulla div, dal momento che l'ambito della direttiva dovrebbe morire e tutti i dati su di esso con esso, ma secondo lo strumento di istantanea dell'heap di Chrome in modalità in incognito, non sta ottenendo non allocato.

Sto cercando di capire perché ciò accade, e perché, se commento la dichiarazione nel metodo bar, non succede.

Procedura per riprodurre:

  1. aperto this file in incognito
  2. strumenti Aprire dev e vanno a profili
  3. Aggiornare la pagina
  4. Clicca Toggle due volte (in modo da ora si vede Nothing sullo schermo ancora una volta
  5. Acquisire un'istantanea dell'heap
  6. Scrivere 'leak' nel filtro in modo da puoi vedere che lo LeakObject esiste ancora quando non dovrebbe esistere davvero.

questo è come dovrebbe essere simile:

The problem

Qualcuno può aiutare/spiegare?

+0

A quanto pare, questo non è un problema in Windows 8, Chrome 42 – Trevor

+0

non possono riprodurre il problema su Ubuntu15/Chome – Bolza

risposta

1

Tutto funziona come previsto, dopo aver seguito i passaggi non vedo alcun oggetto di perdita nell'istantanea.

è possibile aggiungere il seguente codice alla funzione link per vedere che la direttiva è in realtà sempre distruggere

Controller e direttive emettono un evento prima di essere distrutti. È qui che ti viene offerta l'opportunità di distruggere plug-in e ascoltatori e di eseguire la garbage collection. Iscriviti alla portata $. $ Su ('$ distruggere', ...) evento

$scope.$on('$destroy',function(){ 
    //$scope.memoryThatLeaks = null; 
    alert('!'); 
}); 
+0

Quindi stai dicendo che non puoi riprodurre il problema, forse è un problema del sistema operativo/browser. I ', in esecuzione su Chrome 39.0.2171.71 su OSX Yosemite, succede anche ad altri sviluppatori con cui ho parlato. So che la direttiva viene distrutta, ecco perché sembra una perdita di memoria. – Barnash

+5

Il fatto che la funzione sia passata a '$ on ('$ destroy'' viene eseguito non dimostra in realtà che la direttiva venga" distrutta "né che non ci sia una perdita di memoria. – tasseKATT

+0

hai ragione, il fatto che l'evento '$ destroy' sia sparato dimostra che il flusso di Angular funziona come previsto, la direttiva e l'ambito devono essere eliminati. – Moran