简体   繁体   中英

Memory leak with KnockoutJS foreach binding

I run into an issue when running my KnockoutJS v3.4.2 (test) application in Google Chrome.
The memory usage of my page keeps increasing.

The test code is a very simple piece of code, that changes the items in an observable array every second:

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);

Memory usage:

  • In Firefox the memory usage doesn't increase:
    start: 459.6 MB ---> After +- 1 hour: 279.4 MB

  • In chrome the memory usage keeps increasing (memory of individual tab):
    start: 52.912 MB ---> After +- 1 hour: 566.120 MB

  • In edge the memory usage also keeps increasing (memory of individual tab):
    start: 109.560 MB ---> After +- 1 hour: 385.820 MB

Am I doing something wrong in this code snippet? Or would this be a bug in Google Chrome or KnockoutJS?

Apparently this was a browser issue.

When I now run my test project the memory doesn't increase.
The test project can be found here: https://github.com/knockout/knockout/issues/2223

Solved in Google chrome version '58.0.3029.110'.

Even though you're replacing the array in the observable, they're still attached to the DOM. You would need to manually remove them prior to adding new elements to the array.

Something like this:

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);

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM