简体   繁体   中英

How to write function in async mode when $rootscope.broadcast is being used in an infinite loop?

I have a following function which gets called at least 10 times in a second. Every time I have around 100 records which are same except it's LastSeenTime, ReadCount. Since this is a simulator so I know the behaviour however in real time, no of records in an array may vary from 100 - 1000. They may or may not be same. I need to add all distinct records to tagStore which is being displayed in UI thereafter.

$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();
    });

When I runs this code, my browser gets stuck. I also noticed that my CPU, RAM utilization is shooting very high. What I need is that this method should be called only after first method has completed it's execution.

You are invoking multiple digest cycles one after the other, and this usually makes to CPU and memory consumption jump to the sky, and hang the browser.

Use $applyAsync instead of $scope.$apply(); to collect multiple $apply into one $digest cycle. As you can see in the documentation (bold area):

$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.

This loop for (var j = 0; j < $scope.tagStore.length; j++) { is redundant, as it iterates the whole list of tags, for every tag inserted, and half of it on average for every tag updated. Do this instead:

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

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