如何在无限循环中使用 $rootscope.broadcast 时以异步模式编写函数?
How to write function in async mode when $rootscope.broadcast is being used in an infinite loop?
我有一个函数在一秒钟内至少被调用 10 次。每次我有大约 100 条记录,除了 LastSeenTime、ReadCount 之外都是相同的。由于这是一个模拟器,所以我知道实时的行为,数组中的记录不会在 100 - 1000 之间变化。它们可能相同也可能不同。我需要将所有不同的记录添加到之后显示在 UI 中的 tagStore。
$scope.$on('getReadTags', function (event, tags) {
if (($scope.tagStore == null || $scope.tagStore.length == 0) && tags.length != 0) {
$scope.tagStore = tags;
}
else {
for (var i = 0; i < tags.length; i++) {
var notFound = true;
for (var j = 0; j < $scope.tagStore.length; j++) {
if (tags[i].TagID == $scope.tagStore[j].TagID) {
$scope.tagStore[j].ReadCount += tags[i].ReadCount;
$scope.tagStore[j].LastSeenTime = tags[i].LastSeenTime;
$scope.tagStore[j].DiscoveryTime = tags[i].DiscoveryTime;
notFound = false;
break;
}
}
if (!notFound) {
$scope.tagStore.push(tags[i]);
}
}
}
$scope.$apply();
});
当我运行这段代码时,我的浏览器卡住了。我还注意到我的 CPU,RAM 利用率非常高。我需要的是只有在第一个方法完成执行后才应调用此方法。
你在一个接一个地调用多个摘要循环,这通常会使 CPU 和内存消耗飙升,并挂起浏览器。
使用 $applyAsync
而不是 $scope.$apply();
将多个 $apply
收集到一个 $digest 循环中。正如您在文档中看到的(粗体区域):
$applyAsync([exp]); Schedule the invocation of $apply to occur at a
later time. The actual time difference varies across browsers, but is
typically around ~10 milliseconds.
This can be used to queue up multiple expressions which need to be
evaluated in the same digest.
这个循环 for (var j = 0; j < $scope.tagStore.length; j++) {
是多余的,因为它为每个插入的标签迭代整个标签列表,并且平均为每个更新的标签迭代一半。改为这样做:
var tagsMap;
$scope.$on('getReadTags', function (event, tags) {
if (($scope.tagStore == null || $scope.tagStore.length == 0) && tags.length != 0) {
$scope.tagStore = tags;
tagsMap = tags.reduce(function(obj, item) {
obj[item.TagID] = item; // create a map of all tags
}, {});
} else {
for (var i = 0; i < tags.length; i++) {
if(tagsMap[tags[i].TagID]) { // if tag exists in the map, update the tag
tagsMap[tags[i].TagID].ReadCount += tags[i].ReadCount;
tagsMap[tags[i].TagID].LastSeenTime = tags[i].LastSeenTime;
tagsMap[tags[i].TagID].DiscoveryTime = tags[i].DiscoveryTime;
} else { // if tag doesn't exist, push it into the scope, and add it to the tagsMap
$scope.tagStore.push(tags[i]);
tagsMap[tags[i].TagID] = tags[i];
}
}
}
$scope.$applyAsync();
});
我有一个函数在一秒钟内至少被调用 10 次。每次我有大约 100 条记录,除了 LastSeenTime、ReadCount 之外都是相同的。由于这是一个模拟器,所以我知道实时的行为,数组中的记录不会在 100 - 1000 之间变化。它们可能相同也可能不同。我需要将所有不同的记录添加到之后显示在 UI 中的 tagStore。
$scope.$on('getReadTags', function (event, tags) {
if (($scope.tagStore == null || $scope.tagStore.length == 0) && tags.length != 0) {
$scope.tagStore = tags;
}
else {
for (var i = 0; i < tags.length; i++) {
var notFound = true;
for (var j = 0; j < $scope.tagStore.length; j++) {
if (tags[i].TagID == $scope.tagStore[j].TagID) {
$scope.tagStore[j].ReadCount += tags[i].ReadCount;
$scope.tagStore[j].LastSeenTime = tags[i].LastSeenTime;
$scope.tagStore[j].DiscoveryTime = tags[i].DiscoveryTime;
notFound = false;
break;
}
}
if (!notFound) {
$scope.tagStore.push(tags[i]);
}
}
}
$scope.$apply();
});
当我运行这段代码时,我的浏览器卡住了。我还注意到我的 CPU,RAM 利用率非常高。我需要的是只有在第一个方法完成执行后才应调用此方法。
你在一个接一个地调用多个摘要循环,这通常会使 CPU 和内存消耗飙升,并挂起浏览器。
使用 $applyAsync
而不是 $scope.$apply();
将多个 $apply
收集到一个 $digest 循环中。正如您在文档中看到的(粗体区域):
$applyAsync([exp]); Schedule the invocation of $apply to occur at a later time. The actual time difference varies across browsers, but is typically around ~10 milliseconds.
This can be used to queue up multiple expressions which need to be evaluated in the same digest.
这个循环 for (var j = 0; j < $scope.tagStore.length; j++) {
是多余的,因为它为每个插入的标签迭代整个标签列表,并且平均为每个更新的标签迭代一半。改为这样做:
var tagsMap;
$scope.$on('getReadTags', function (event, tags) {
if (($scope.tagStore == null || $scope.tagStore.length == 0) && tags.length != 0) {
$scope.tagStore = tags;
tagsMap = tags.reduce(function(obj, item) {
obj[item.TagID] = item; // create a map of all tags
}, {});
} else {
for (var i = 0; i < tags.length; i++) {
if(tagsMap[tags[i].TagID]) { // if tag exists in the map, update the tag
tagsMap[tags[i].TagID].ReadCount += tags[i].ReadCount;
tagsMap[tags[i].TagID].LastSeenTime = tags[i].LastSeenTime;
tagsMap[tags[i].TagID].DiscoveryTime = tags[i].DiscoveryTime;
} else { // if tag doesn't exist, push it into the scope, and add it to the tagsMap
$scope.tagStore.push(tags[i]);
tagsMap[tags[i].TagID] = tags[i];
}
}
}
$scope.$applyAsync();
});