#angularjs #performance #optimization #ng-bind #ng-filter
#angularjs #Производительность #оптимизация #ng-bind #ng-filter
Вопрос:
В моем приложении angular js у меня есть массив объектов $scope.time
, которые содержат имя, текущее время и другое определенное время в миллисекундах. Во внешнем интерфейсе я использую ng-bind
для вычисления разницы между этими двумя временами и отображения ее в формате H: m: s. Пожалуйста, запустите приведенный ниже код.
var app = angular.module('angularapp', []);
app.filter("msTotime", function() {
return function(timee,started,ended) {
var startDate = new Date(started);
var endDate = new Date(ended);
var milisecondsDiff = endDate - startDate;
var final = Math.floor(milisecondsDiff/(1000*60*60)).toLocaleString(undefined, {minimumIntegerDigits: 2}) ":" (Math.floor(milisecondsDiff/(1000*60))%60).toLocaleString(undefined, {minimumIntegerDigits: 2}) ":" (Math.floor(milisecondsDiff/1000)%60).toLocaleString(undefined, {minimumIntegerDigits: 2}) ;
var defaulttime = '00:00:00';
if(final == '-01:-01:-01'){
return defaulttime;
}
else {
return final;
}
}
});
app.controller('list', function($scope,$window) {
$scope.time = [{"game":"Halo","now":1554805270181,"time":1554794475267},
{"game":"CODuty","now":1554805270181,"time":1554802957031},
{"game":"WOF","now":1554805270181,"time":1554732154093},
{"game":"WarCraft","now":1554805270181,"time":1554803456875},
{"game":"POP","now":1554805270181,"time":1554803456275},
{"game":"RedBulls","now":1554805270181,"time":1554800620012},
{"game":"Eragon","now":1554805270181,"time":1554433320072}];
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.10/angular.min.js"></script>
<div ng-app="angularapp">
<div ng-controller="list" >
<div ng-repeat="timer in time">
<h5>{{timer.game}}</h5><hr>
Milliseconds to H:M:S for {{timer.game}} <p style="display:inline-block" ng-bind="realtime | msTotime:timer.time:timer.now"></p><br>
</div>
</div>
</div>
$scope.time
Массив является динамическим, поскольку я получаю эти данные из api (я жестко определил его здесь для демонстрации).
Приведенный выше код работает плавно, когда у меня есть несколько объектов в $scope.time
массиве. Но когда есть тысячи объектов, мой браузер начинает отставать, поскольку msTotime
фильтр продолжает вычислять разницу между миллисекундами, преобразует ее H:m:s
и привязывает к интерфейсу.
Теперь проблема в том, что мой браузер потребляет 40 процентов процессора при наличии 1000 объектов. Я считаю, что это не проблема, ng-repeat
поскольку, когда я прокомментировал, <p style="display:inline-block" ng-bind="realtime | msTotime:timer.time:timer.now">
загрузка процессора составляла всего 5 процентов с более чем 1000 объектами.
Есть ли какой-либо способ оптимизировать ng-bind
директиву здесь или выполнить вычисление времени каким-либо другим способом, чтобы вычисления, выполняемые msTotime
filter, не потребляли так много ЦП.
Комментарии:
1. вы можете использовать track by в цикле повтора, чтобы список обновлялся только при изменении данных
Ответ №1:
Я бы предложил использовать Lodash https://lodash.com библиотека для добавления разницы во времени в каждый объект вместо того, чтобы использовать directive
для этого. поэтому каждый раз, когда вы получаете данные из запроса _.each
, выполняйте ту же операцию и вставляйте var realtime
.
var app = angular.module('angularapp', []);
app.controller('list', function($scope,$window) {
$scope.time = [
{"game":"Halo","now":1554805270181,"time":1554794475267},
{"game":"CODuty","now":1554805270181,"time":1554802957031},
{"game":"WOF","now":1554805270181,"time":1554732154093},
{"game":"WarCraft","now":1554805270181,"time":1554803456875},
{"game":"POP","now":1554805270181,"time":1554803456275},
{"game":"RedBulls","now":1554805270181,"time":1554800620012},
{"game":"Eragon","now":1554805270181,"time":1554433320072}
];
_.each($scope.time, function(obj, index){
var startDate = new Date(obj.time);
var endDate = new Date(obj.now);
var milisecondsDiff = endDate - startDate;
var final = Math.floor(milisecondsDiff / (1000 * 60 * 60)).toLocaleString(undefined, {
minimumIntegerDigits: 2
}) ":" (Math.floor(milisecondsDiff / (1000 * 60)) % 60).toLocaleString(undefined, {
minimumIntegerDigits: 2
}) ":" (Math.floor(milisecondsDiff / 1000) % 60).toLocaleString(undefined, {
minimumIntegerDigits: 2
});
var defaulttime = '00:00:00';
if (final == '-01:-01:-01') {
obj.realtime = defaulttime;
} else {
obj.realtime = final;
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.10/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.core.min.js"></script>
<div ng-app="angularapp">
<div ng-controller="list" >
<div ng-repeat="timer in time">
<h5>{{timer.game}}</h5><hr/>
Milliseconds to H:M:S for {{timer.game}} <p style="display:inline-block;">{{timer.realtime}}</p><br>
</div>
</div>
</div>
Комментарии:
1. Я попробую это