কীভাবে কোনও পৃষ্ঠায় মোট ঘড়ির সংখ্যা গণনা করবেন?


144

পুরো পৃষ্ঠায় কৌনিক ঘড়ির সংখ্যা গণনা করার জন্য কি জাভাস্ক্রিপ্টে কোনও উপায় আছে?

আমরা বাটারং ব্যবহার করি তবে এটি সর্বদা আমাদের প্রয়োজন অনুসারে হয় না। আমাদের অ্যাপ্লিকেশন বড় এবং আমরা ঘড়ির সংখ্যা খুব বেশি বাড়ছে কিনা তা পরীক্ষা করতে স্বয়ংক্রিয় পরীক্ষাগুলি ব্যবহার করতে আগ্রহী।

প্রতি-নিয়ামক ভিত্তিতে ঘড়ি গণনা করাও দরকারী would

সম্পাদনা : এখানে আমার চেষ্টা। এটি ক্লাস এনজিও-স্কোপ সহ সমস্ত কিছুতে ঘড়ি গণনা করে।

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

প্রতি নিয়ামক সহজ। প্রত্যেকের $scopeসেই নিয়ামকের উপরে নজরদারি সংখ্যার সাথে একটি $$ প্রহরীদের অ্যারে থাকে (ভাল, আপনার যদি কিছু এনজি-রিপিট থাকে বা এমন কিছু থাকে যা অন্য সুযোগ তৈরি করে, তবে এটি ভাল কাজ করে না)। তবে আমি মনে করি পুরো অ্যাপটিতে সমস্ত ঘড়ি দেখার কোনও উপায় নেই।
যিশু রদ্রিগেজ

উত্তর:


220

(আপনি পরিবর্তন করার প্রয়োজন হতে পারে 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);
})();
  • এই উত্তরটি চিহ্নিত করার জন্য এরিলেমের জন্য ধন্যবাদ $isolateScopeঅনুসন্ধানটি অনুপস্থিত এবং পর্যবেক্ষকরা সম্ভবত তার উত্তর / মন্তব্যে নকল হচ্ছেন।

  • বেন 2307 ধন্যবাদ আপনাকে উল্লেখ করার জন্য যে এর 'body'পরিবর্তনের প্রয়োজন হতে পারে to


মূল

আমি এইচটিএমএল উপাদানটির ডেটা অ্যাট্রিবিউটটি তার শ্রেণীর পরিবর্তে পরীক্ষা না করেই একই কাজ করেছি। আমি তোমার এখানে দৌড়েছি:

http://fluid.ie/

আমি পেয়েছি এবং আমি পেয়েছি 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');
        }
    }
}

এবং কিছুই মুদ্রিত হয়নি, সুতরাং আমি অনুমান করছি যে খনিটি ভাল (এটিতে আরও ঘড়িগুলি পাওয়া গেছে) - তবে খনিটি সমাধানের সেটটির উপযুক্ত উপসেট নয় তা নিশ্চিতভাবে জানতে আমার অন্তরঙ্গ কৌণিক জ্ঞানের অভাব রয়েছে।


2
আমি অনুরূপ কিছু করার চেষ্টা করছি এবং এই স্নিপেটকে খুব সহায়ক বলে মনে করেছি। একটি জিনিস যা আমি আমার কাছে স্পষ্ট করার মতো বলে মনে করি তা হ'ল 'রুট' এমন কোনও উপাদানের সাথে সেট করা উচিত যা 'এনজি-অ্যাপ' বৈশিষ্ট্যটি রয়েছে, কারণ সেখানে $ রুটস্কোপটি রাখা হয়েছে। আমার অ্যাপে এটি 'এইচটিএমএল' ট্যাগে রয়েছে on আপনার স্ক্রিপ্টটি যেমন চালাচ্ছেন তেমনি আমার অ্যাপ্লিকেশনটিতে $ প্রহরীদের মধ্যে থাকা $ রুটস্কোপটি মিস হয়েছে।
আমিরি

উপরের কোডটিতে আমি একটি সমস্যা পেয়েছি: যদি কোনও শিশু উপাদানটির নিজস্ব সুযোগ থাকে তবে এখন পর্যবেক্ষকরা $ সুযোগ "না দিতেন কি? আমার মনে হয় আপনার ধাক্কা দেওয়ার আগে এই জাতীয় কিছু যুক্ত করা উচিত (আমি লোডাশ ব্যবহার করছি): যদি (! _। থাকে (প্রহরী, প্রহরী)) {ওয়াচার্স.পুশ (প্রহরী); }
বেন 2307

2
এটি ডোম উপাদানগুলির সাথে সংযুক্ত সমস্ত প্রহরীকে পায়। আপনি যদি কোনও ডিওএম উপাদান মুছে ফেলেন, তবে কি সম্পর্কিত $scopeএবং $$watcherস্বয়ংক্রিয়ভাবে ক্লিনআপ রয়েছে , বা তাদের দ্বারা সম্পাদিত কোনও পারফরম্যান্স রয়েছে?
সিম্পলজি

এটি কি নতুন এক-সময়ের বাইন্ডিং বৈশিষ্ট্যটিকে বিবেচনা করে? আপনার গণনা কি এই জাতীয় বাধ্যবাধকতা বাদ দেয়?
সিস্টেমে

10
কেবলমাত্র শীর্ষস্থানীয়: আপনি যদি $compileProvider.debugInfoEnabled(false);আপনার প্রকল্পে ব্যবহার করেন তবে এই স্নিপেট শূন্য পর্যবেক্ষকদের গণনা করবে।
মাইকেল Klöpzig

16

আমি মনে করি যে উল্লিখিত পদ্ধতিগুলি সঠিক নয় কারণ তারা একই সুযোগে দ্বিগুণকে লক্ষ্য করে। এখানে আমার বুকমার্কলেটের সংস্করণটি রয়েছে:

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

এটি পর্যবেক্ষকদের বিশ্লেষণের জন্য আরও কিছু বিশদ দেখায়।


12

স্কোপ স্ট্রাকচারগুলি পরিদর্শন করার উপর ভিত্তি করে এখানে একটি হ্যাকি সমাধান আমি একসাথে রেখেছি। এটা কাজ "মনে হয়"। আমি নিশ্চিত না যে এটি কতটা সঠিক এবং এটি অবশ্যই কিছু অভ্যন্তরীণ এপিআইয়ের উপর নির্ভর করে। আমি অ্যাঙ্গুলারজ ব্যবহার করছি 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);
    };

এটি আমার মূল সমাধানের মতো (সম্পাদনা ইতিহাস দেখুন)। আমি অন্য পদ্ধতিতে চলে এসেছি কারণ আমি মনে করি স্কোপ শ্রেণিবিন্যাসের পথ চললে বিচ্ছিন্ন সুযোগগুলি মিস হবে।
ty।

3
যদি আমি নিয়ামকের সাথে $rootScope.$new(true)বা $scope.$new(true)যেখানে বিচ্ছিন্ন সুযোগ তৈরি করি $scope, তবে শ্রেণিবিন্যাসে হাঁটলে এখনও সেই সুযোগটি খুঁজে পাওয়া যায়। আমি মনে করি এর অর্থ যে প্রোটোটাইপগুলি সংযুক্ত নয় তার পরিবর্তে সুযোগটি শ্রেণিবদ্ধ নয়।
ইয়ান উইলসন

হ্যাঁ, সমস্ত স্কোপগুলি $ রুটস্কোপ থেকে নেমে আসে, বিচ্ছিন্ন স্কোপে কেবল উত্তরাধিকার "বিচ্ছিন্ন" হয় is বিচ্ছিন্ন স্কোপগুলি প্রায়শই নির্দেশিকায় ব্যবহৃত হয় - এখানে আপনি পিতামাতার কাছ থেকে অ্যাপ-ভেরিয়েবল হস্তক্ষেপ করতে চান না।
চিহ্নমারিজনিসেন

আপনি যদি তৈরি করেন এমন স্কোপগুলি সনাক্ত করার চেষ্টা করছেন তবে পরিষ্কার করছেন না, এই পদ্ধতিটি আরও উন্নত। আমার ক্ষেত্রে, ডিওএম ক্রলিং সর্বদা একই স্কোপগুলি দেখায় তবে যা ডোম সংযুক্ত নয় তারা ছায়াময়ভূমিতে বহুগুণ হয়।
সিম্পলজি

10

একটি নতুন ক্রোম প্লাগইন রয়েছে যা স্বয়ংক্রিয়ভাবে বর্তমান মোট পর্যবেক্ষক এবং আপনার অ্যাপের যে কোনও সময় শেষ পরিবর্তন (+/-) দেখায় ... এটি খাঁটি দুর্দান্ত।

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


এটি প্রকৃতপক্ষে প্রযোজ্য
সুজিত ওয়াই কুলকার্নি

9

আমি সম্প্রতি আমার অ্যাপ্লিকেশনটিতে উচ্চ সংখ্যক নজরদারিদের সাথে লড়াই করার সময়, আমি একটি দুর্দান্ত লাইব্রেরি পেয়েছি, যার নাম এনজি-স্ট্যাটাস - https://github.com/kentcdodds/ng-stats । এটির ন্যূনতম সেটআপ রয়েছে এবং আপনাকে বর্তমান পৃষ্ঠাতে + ডাইজেস্ট চক্রের দৈর্ঘ্যের উপর নজরদারিদের সংখ্যা দেয়। এটি একটি ছোট রিয়েল-টাইম গ্রাফও প্রজেক্ট করতে পারে।


8

জ্যারেডের উত্তরটির মতো শব্দের জন্য ছোটখাটো উন্নতি ।

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

2
যেহেতু আপনি jQuery নির্বাচনকারী ব্যবহার করছেন না, আপনি) () এর পরিবর্তে কৌনিক.এলিমেন্ট () ব্যবহার করতে পারেন
দাড়িওয়ালাডিনুকজেক ek

8

অ্যাঙ্গুলারজেএস ১.৩.২ countWatchersএ এনজিমক মডিউলে একটি পদ্ধতি যুক্ত করা হয়েছিল:

/ **
 * @ngdoc পদ্ধতি
 * @ নাম $ রুটস্কোপ.স্কোপ # $ কাউন্ট ওয়াচচার্স
 * @ মডিউল এনজিমন
 * @ বিবরণ
 * বর্তমান সুযোগের প্রত্যক্ষ এবং অপ্রত্যক্ষ শিশু স্কোপের সমস্ত প্রহরীকে গণনা করে।
 *
 * বর্তমান ক্ষেত্রের প্রহরীগণ গণনাতে অন্তর্ভুক্ত এবং একইভাবে সমস্ত পর্যবেক্ষকও রয়েছেন
 * শিশু স্কোপগুলি বিচ্ছিন্ন করুন।
 *
 * @ পুনর্বারণ {সংখ্যা wat মোট পর্যবেক্ষকের সংখ্যা।
 * /

  ফাংশন কাউন্টওয়াচার্স () 
   {
   var রুট = কৌণিক.ইলেট (ডকুমেন্ট) .আইনজেক্টর ()। get ('$ রুটস্কোপ');
   var গণনা = মূল। c প্রহরী? রুট। c প্রহরী। দৈর্ঘ্য: 0; // বর্তমান সুযোগ অন্তর্ভুক্ত
   var प्रलंबितChildHeads = [মূল। $$ চাইল্ডহিড];
   var কারেন্টস্কোপ;

   যখন (ছন্দহিল্ডস দৈর্ঘ্য বিচারাধীন) 
    {
    কারেন্টস্কোপ = মুলতুবিচাইল্ডহাইডস.শફ્ટ ();

    যখন (কারেন্টস্কোপ) 
      {
      গণনা + = কারেন্টস্কোপ। $$ প্রহরী? কারেন্টস্কোপ। c প্রহরী। দৈর্ঘ্য: 0;
      pendingChildHeads.push (currentScope $$ childHead।);
      কারেন্টস্কোপ = কারেন্টস্কোপ। $$ পরবর্তীসিলিং;
      }
    }

   রিটার্ন গণনা;
   }

তথ্যসূত্র


1
ধন্যবাদ! আমি পরিবর্তন angular.element(document)করতে angular.element('[ng-app]')এবং একটি সতর্কতা সঙ্গে একটি বুকমার্কলেটে এটা করা:alert('found ' + countWatchers() + ' watchers');
undefined

4

আমি সরাসরি $digestফাংশন থেকে নীচের কোডটি নিয়েছি । অবশ্যই, আপনার সম্ভবত document.bodyনীচে অ্যাপ্লিকেশন উপাদান নির্বাচনকারী ( ) আপডেট করতে হবে need

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


1

এটি আমি ব্যবহৃত ফাংশনগুলি:

/**
 * @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);
  };

})();

এই ফাংশনটি একই স্কোপটিকে একাধিকবার গণনা করতে একটি হ্যাশ ব্যবহার করে।


আমি element.data()কখনও কখনও অপরিজ্ঞাত বা কিছু হতে পারে বলে মনে করি (কমপক্ষে একটি 1.0.5 অ্যাপ্লিকেশনটিতে যখন আমি এই স্নিপডে দৌড়ে গিয়ে কল করার চেষ্টা করেছি তখন আমি একটি ত্রুটি পেয়েছি countWatchers)। শুধু এফওয়াইআই।
জ্যারেড

1

মোট সংখ্যা পর্যবেক্ষক সংগ্রহ করার জন্য লার্স Eidদনেস ব্লগ দ্বারা http://lareidnes.com/2014/11/05/angularjs-the-bad-partts/ এ একটি পুনরাবৃত্ত অনুষ্ঠান প্রকাশিত হয়েছে । আমি এখানে পোস্ট করা ফাংশন এবং তার ব্লগে তার পোস্ট করা একটি ব্যবহার করে ফলাফলের সাথে তুলনা করি যা কিছুটা বেশি সংখ্যার উত্পন্ন হয়েছে। কোনটি আরও সঠিক তা আমি বলতে পারি না। এখানে একটি জুড়ে রেফারেন্স হিসাবে যুক্ত।

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;

দ্রষ্টব্য: আপনার কৌনিক অ্যাপ্লিকেশানের জন্য আপনার "এনজি-অ্যাপ্লিকেশন" "ডেটা-এনজি-অ্যাপ" পরিবর্তন করতে হবে change


1

প্ল্যান্টিয়ানদের উত্তরটি দ্রুত: https://stackoverflow.com/a/18539624/258482

এখানে একটি ফাংশন যা আমি হাতে লিখেছি is আমি পুনরাবৃত্তি ফাংশনগুলি ব্যবহার করার বিষয়ে ভাবি নি, তবে পরিবর্তে আমি এটিই করেছি। এটা ঝোঁক হতে পারে, আমি জানি না।

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

তারপরে এটি আপনার সর্বোচ্চ নিয়ামকের ভিতরে রাখুন (যদি আপনি কোনও বৈশ্বিক নিয়ামক ব্যবহার করেন)।

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

এবং অবশেষে একটি বুকমার্কেট:

javascript:logScope();

0

এই প্রশ্নে কিছুটা দেরি হলেও আমি এটি ব্যবহার করি

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

আপনি সঠিক ক্যোয়ারী নির্বাচনকারী নির্বাচন করেছেন তা নিশ্চিত করুন make

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.