2017-04-06 3 views
10

Ich stoße auf ein Problem beim Ausführen meiner Anwendung KnockoutJS v3.4.2 (Test) in Google Chrome.
Die Speichernutzung meiner Seite nimmt weiter zu.Speicherleck mit KnockoutJS foreach Bindung

Der Testcode ist ein sehr einfaches Stück Code, dass jeder zweite die Elemente in einer beobachtbaren Matrix ändert:

HTML:

<html> 
    <head> 
     <title>KnockoutJS</title> 
    </head> 
    <body> 
     <h1>Foreach test</h1> 
     <ul id="ul-numbers" data-bind="foreach: { data: listOfItems }"> 
      <li> 
       <span data-bind="text: $data"></span> 
      </li> 
     </ul> 

     <script type="text/javascript" src="./lib/knockout.js"></script> 
     <script type="text/javascript" src="./index.js"></script> 
    </body> 
</html> 

JavaScript:

var vm = { 
    listOfItems: ko.observableArray() 
}; 

window.setInterval(function updateList(){ 
    var array = []; 

    for(var i = 0 ; i < 1000; i++){ 
     var num = Math.floor(Math.random() * 500); 
     array.push(num); 
    } 

    vm.listOfItems(array); 
}, 1000); 

ko.applyBindings(vm); 

Speicherverbrauch:

  • In Firefox die Speichernutzung nicht erhöht:
    Start: 459,6 MB ---> Nach + - 1 Stunde: 279,4 MB

  • In Chrom der Speicherverbrauch hält (Erinnerung an einzelnen Registerkarten) zu erhöhen:
    Start: 52,912 MB ---> Nach + - 1 Stunde: 566,120 MB

  • der Speicherverbrauch hält auch zu (Speicher einzelner Reiter) In Rand:
    Start: 109,560 MB ---> Nach + - 1 Stunde: 385,820 MB

Mache ich etwas falsch in diesem Codeausschnitt? Oder wäre das ein Fehler in Google Chrome oder KnockoutJS?

+1

Was passiert, wenn Sie nicht 'array' verwenden und stattdessen' vm.listOfItems.removeAll() 'am Anfang der Funktion aufrufen, dann' vm.listOfItems.push (num) 'innerhalb der Schleife (ohne den Aufruf von 'vm.listOfItems (array)' am Ende)? – haim770

+0

Alternativ können Sie 'vm.listOfItems (array.slice (0));' versuchen, um zu verhindern, dass Knockout den Verweis auf das ursprüngliche 'array' behält und dem GC erlaubt, ihn zu entfernen – haim770

+0

Getestet mit dem removeAll, aber immer noch das gleiche Verhalten. –

Antwort

1

Anscheinend war dies ein Browser-Problem.

Wenn ich jetzt mein Testprojekt starte, erhöht sich der Speicher nicht. Das Testprojekt finden Sie hier: https://github.com/knockout/knockout/issues/2223

Gelöst in Google Chrome-Version '58 .0.3029.110 '.

0

Obwohl Sie das Array im Observable ersetzen, sind sie immer noch an das DOM angeschlossen. Sie müssten diese manuell entfernen, bevor Sie dem Array neue Elemente hinzufügen.

Etwas wie folgt aus:

var vm = { 
    listOfItems: ko.observableArray() 
}; 

window.setInterval(function updateList(){ 
    var array = []; 
    vm.listOfItems.removeAll();//<--this is the important line 
    for(var i = 0 ; i < 1000; i++){ 
     var num = Math.floor(Math.random() * 500); 
     array.push(num); 
    } 

    vm.listOfItems(array); 
}, 1000); 

ko.applyBindings(vm); 

Siehe # 2 in diesem Beitrag: https://auth0.com/blog/four-types-of-leaks-in-your-javascript-code-and-how-to-get-rid-of-them/

+0

Das löst das Problem nicht, wir haben das schon ausprobiert. (siehe Kommentare zu meiner Frage) –

Verwandte Themen