Утечка памяти с помощью привязки KnockoutJS foreach

Я столкнулся с проблемой при запуске приложения NockoutJS v3.4.2 (test) в Google Chrome.
Использование моей страницы памяти увеличивается.

Тест-код - очень простой фрагмент кода, который меняет элементы в наблюдаемом массиве каждую секунду:

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

Использование памяти:

  • В Firefox использование памяти не увеличивается:
      начало: 459.6 МБ --- > После + - 1 час: 279.4 МБ

  • В хроме использование памяти увеличивается (память отдельных вкладок):
      начало: 52.912 МБ --- > После + - 1 час: 566.120 МБ

  • В краю использование памяти также увеличивается (память отдельных вкладок):
      начало: 109,560 МБ --- > После + - 1 час: 385.820 МБ

Я делаю что-то неправильно в этом фрагменте кода? Или это будет ошибкой в ​​Google Chrome или KnockoutJS?

Ответ 1

По-видимому, это была проблема с браузером.

Когда я запускаю свой тестовый проект, память не увеличивается.
Проект тестирования можно найти здесь: https://github.com/knockout/knockout/issues/2223

Решено в версии Google chrome версии '58.0.3029.110 '.

Ответ 2

Даже если вы заменяете массив в наблюдаемом, они все еще привязаны к DOM. Вам нужно будет вручную удалить их до добавления новых элементов в массив.

Что-то вроде этого:

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

См. # 2 в этом сообщении: https://auth0.com/blog/four-types-of-leaks-in-your-javascript-code-and-how-to-get-rid-of-them/