programing tip

페이지에서 총 시계 수를 계산하는 방법은 무엇입니까?

itbloger 2020. 6. 18. 21:31
반응형

페이지에서 총 시계 수를 계산하는 방법은 무엇입니까?


JavaScript에서 전체 페이지의 각도 시계 수를 계산하는 방법이 있습니까?

우리는 Batarang을 사용 하지만 항상 우리의 요구에 맞는 것은 아닙니다. 우리의 응용 프로그램은 크며 자동 테스트를 사용하여 시계 수가 너무 많이 올라가는 지 확인하고 싶습니다.

컨트롤러별로 시계를 계산하는 것도 유용합니다.

편집 : 여기 내 시도입니다. 그것은 클래스 ng-scope로 모든 시계를 계산합니다.

(function () {
    var elts = document.getElementsByClassName('ng-scope');
    var watches = [];
    var visited_ids = {};
    for (var i=0; i < elts.length; i++) {
       var scope = angular.element(elts[i]).scope();
       if (scope.$id in visited_ids) 
         continue;
       visited_ids[scope.$id] = true;
       watches.push.apply(watches, scope.$$watchers);
    }
    return watches.length;
})();

( 을 넣은 곳이나 장소 를 바꿔야 body수도 html있습니다 ng-app)

(function () { 
    var root = angular.element(document.getElementsByTagName('body'));

    var watchers = [];

    var f = function (element) {
        angular.forEach(['$scope', '$isolateScope'], function (scopeProperty) { 
            if (element.data() && element.data().hasOwnProperty(scopeProperty)) {
                angular.forEach(element.data()[scopeProperty].$$watchers, function (watcher) {
                    watchers.push(watcher);
                });
            }
        });

        angular.forEach(element.children(), function (childElement) {
            f(angular.element(childElement));
        });
    };

    f(root);

    // Remove duplicate watchers
    var watchersWithoutDuplicates = [];
    angular.forEach(watchers, function(item) {
        if(watchersWithoutDuplicates.indexOf(item) < 0) {
             watchersWithoutDuplicates.push(item);
        }
    });

    console.log(watchersWithoutDuplicates.length);
})();
  • 이 답변에 지적한 것에 대한 erilem 덕분에 $isolateScope검색 이 누락 되었고 감시자가 잠재적으로 자신의 답변 / 댓글에 복제되고 있습니다.

  • 'body'변경이 필요할 수 있음 을 지적한 Ben2307에게 감사합니다 .


기발한

클래스가 아닌 HTML 요소의 데이터 속성을 확인한 것을 제외하고는 동일한 작업을 수행했습니다. 나는 너를 여기에서 달렸다.

http://fluid.ie/

83을 얻었습니다. 나는 내 것을 달렸고 121을 얻었습니다.

(function () { 
    var root = $(document.getElementsByTagName('body'));
    var watchers = [];

    var f = function (element) {
        if (element.data().hasOwnProperty('$scope')) {
            angular.forEach(element.data().$scope.$$watchers, function (watcher) {
                watchers.push(watcher);
            });
        }

        angular.forEach(element.children(), function (childElement) {
            f($(childElement));
        });
    };

    f(root);

    console.log(watchers.length);
})();

나는 또한 이것을 내 안에 넣었다.

for (var i = 0; i < watchers.length; i++) {
    for (var j = 0; j < watchers.length; j++) {
        if (i !== j && watchers[i] === watchers[j]) {
            console.log('here');
        }
    }
}

그리고 아무것도 인쇄되지 않았으므로 광산이 더 나을 것입니다 (더 많은 시계를 찾았다는 점). 그러나 광산이 솔루션 세트의 적절한 하위 집합이 아님을 알 수있는 친밀한 각도 지식이 부족합니다.


언급 된 접근 방식은 동일한 범위에서 두 배의 감시자를 계산하기 때문에 부정확하다고 생각합니다. 내 북마크릿 버전은 다음과 같습니다.

https://gist.github.com/DTFagus/3966db108a578f2eb00d

또한 감시자 분석에 대한 자세한 내용도 보여줍니다.


다음은 범위 구조 검사를 기반으로 한 해키 솔루션입니다. 작동하는 것은 "보인다". 이것이 얼마나 정확한지 잘 모르겠으며 내부 API에 따라 다릅니다. angularjs 1.0.5를 사용하고 있습니다.

    $rootScope.countWatchers = function () {
        var q = [$rootScope], watchers = 0, scope;
        while (q.length > 0) {
            scope = q.pop();
            if (scope.$$watchers) {
                watchers += scope.$$watchers.length;
            }
            if (scope.$$childHead) {
                q.push(scope.$$childHead);
            }
            if (scope.$$nextSibling) {
                q.push(scope.$$nextSibling);
            }
        }
        window.console.log(watchers);
    };

앱에 언제든지 현재 총 시청자 수와 마지막 변경 사항 (+/-)을 자동으로 표시하는 새로운 크롬 플러그인이 있습니다.

https://chrome.google.com/webstore/detail/angular-watchers/nlmjblobloedpmkmmckeehnbfalnjnjk


최근에 내 응용 프로그램에서 많은 수의 감시자와 씨름하고 있었기 때문에 ng-stats - https : //github.com/kentcdodds/ng-stats 라는 훌륭한 라이브러리를 발견했습니다 . 최소 설정으로 현재 페이지에있는 감시자 수 + 다이제스트주기 길이를 제공합니다. 작은 실시간 그래프를 투사 할 수도 있습니다.


AngularJS 1.3.2에서는 countWatchersngMock 모듈에 메소드가 추가되었습니다.

/ **
 * @ngdoc 방법
 * @name $ rootScope.Scope # $ countWatchers
 * @ 모듈 ngMock
 * @ 설명
 * 현재 범위의 직접 및 간접 하위 범위의 모든 감시자를 계산합니다.
 *
 * 현재 범위의 감시자도 카운트에 포함되며 모든 감시자도
 * 하위 범위를 분리합니다.
 *
 * @returns {number} 총 감시자 수입니다.
 * /

 함수 countWatchers () 
   {
   var root = angular.element (document) .injector (). get ( '$ rootScope');
   var count = root. $$ watchers? root. $$ watchers.length : 0; // 현재 범위를 포함
   var pendingChildHeads = [root. $$ childHead];
   var currentScope;

   while (pendingChildHeads.length) 
    {
    currentScope = pendingChildHeads.shift ();

    while (currentScope) 
      {
      count + = currentScope. $$ watchers? currentScope. $$ watchers.length : 0;
      pendingChildHeads.push (currentScope. $$ childHead);
      currentScope = currentScope. $$ nextSibling;
      }
    }

   반품 횟수;
   }

참고 문헌


Jared의 답변과 같은 단어의 사소한 개선 .

(function () {
    var root = $(document.getElementsByTagName('body'));
    var watchers = 0;

    var f = function (element) {
        if (element.data().hasOwnProperty('$scope')) {
            watchers += (element.data().$scope.$$watchers || []).length;
        }

        angular.forEach(element.children(), function (childElement) {
            f($(childElement));
        });
    };

    f(root);

    return watchers;
})();

$digest함수 자체 에서 직접 아래 코드를 가져 왔습니다 . 물론 document.body맨 아래에서 애플리케이션 요소 선택기 ( ) 를 업데이트해야 할 수도 있습니다 .

(function ($rootScope) {
    var watchers, length, target, next, count = 0;

    var current = target = $rootScope;

    do {
        if ((watchers = current.$$watchers)) {
            count += watchers.length;
        }

        if (!(next = (current.$$childHead ||
                (current !== target && current.$$nextSibling)))) {
            while (current !== target && !(next = current.$$nextSibling)) {
                current = current.$parent;
            }
        }
    } while ((current = next));

    return count;
})(angular.element(document.body).injector().get('$rootScope'));


이것이 내가 사용하는 기능입니다.

/**
 * @fileoverview This script provides a window.countWatchers function that
 * the number of Angular watchers in the page.
 *
 * You can do `countWatchers()` in a console to know the current number of
 * watchers.
 *
 * To display the number of watchers every 5 seconds in the console:
 *
 * setInterval(function(){console.log(countWatchers())}, 5000);
 */
(function () {

  var root = angular.element(document.getElementsByTagName('body'));

  var countWatchers_ = function(element, scopes, count) {
    var scope;
    scope = element.data().$scope;
    if (scope && !(scope.$id in scopes)) {
      scopes[scope.$id] = true;
      if (scope.$$watchers) {
        count += scope.$$watchers.length;
      }
    }
    scope = element.data().$isolateScope;
    if (scope && !(scope.$id in scopes)) {
      scopes[scope.$id] = true;
      if (scope.$$watchers) {
        count += scope.$$watchers.length;
      }
    }
    angular.forEach(element.children(), function (child) {
      count = countWatchers_(angular.element(child), scopes, count);
    });
    return count;
  };

  window.countWatchers = function() {
    return countWatchers_(root, {}, 0);
  };

})();

이 함수는 해시를 사용하여 동일한 범위를 여러 번 계산하지 않습니다.


There is a recursive function published by Lars Eidnes' blog at http://larseidnes.com/2014/11/05/angularjs-the-bad-parts/ to collect the total number watchers. I compare the result using the function posted here and the one his posted in his blog, which has generated slightly higher number. I cannot tell which one is more accurate. Just added here as a across reference.

function getScopes(root) {
    var scopes = [];
    function traverse(scope) {
        scopes.push(scope);
        if (scope.$$nextSibling)
            traverse(scope.$$nextSibling);
        if (scope.$$childHead)
            traverse(scope.$$childHead);
    }
    traverse(root);
    return scopes;
}
var rootScope = angular.element(document.querySelectorAll("[ng-app]")).scope();
var scopes = getScopes(rootScope);
var watcherLists = scopes.map(function(s) { return s.$$watchers; });
_.uniq(_.flatten(watcherLists)).length;

NOTE: you might need change "ng-app" to "data-ng-app" for your Angular app.


Plantian's answer is faster: https://stackoverflow.com/a/18539624/258482

Here is a function which I hand-wrote. I didn't think about using recursive functions, but this is what I did instead. It might be leaner, I don't know.

var logScope; //put this somewhere in a global piece of code

Then put this inside your highest controller ( if you use a global controller ).

$scope.$on('logScope', function () { 
    var target = $scope.$parent, current = target, next;
    var count = 0;
    var count1 = 0;
    var checks = {};
    while(count1 < 10000){ //to prevent infinite loops, just in case
        count1++;
        if(current.$$watchers)
            count += current.$$watchers.length;

        //This if...else is also to prevent infinite loops. 
        //The while loop could be set to true.
        if(!checks[current.$id]) checks[current.$id] = true;
        else { console.error('bad', current.$id, current); break; }
        if(current.$$childHead) 
            current = current.$$childHead;
        else if(current.$$nextSibling)
            current = current.$$nextSibling;
        else if(current.$parent) {
            while(!current.$$nextSibling && current.$parent) current = current.$parent;
            if(current.$$nextSibling) current = current.$$nextSibling;
            else break;
        } else break;
    }
    //sort of by accident, count1 contains the number of scopes.
    console.log('watchers', count, count1);
    console.log('globalCtrl', $scope); 
   });

logScope = function () {
    $scope.$broadcast('logScope');
};

And finally a bookmarket:

javascript:logScope();

A bit late to this question, but I use this

angular.element(document.querySelector('[data-ng-app]')).scope().$$watchersCount

just make sure you use the correct querySelector.

참고URL : https://stackoverflow.com/questions/18499909/how-to-count-total-number-of-watches-on-a-page

반응형