如何在无限循环中使用 $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();
});