Copy as link into bookmark. Outputs into console.
Created
August 12, 2014 14:22
-
-
Save DTFagus/3966db108a578f2eb00d to your computer and use it in GitHub Desktop.
Bookmarklet to analyse angular watchers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
javascript: (function() { | |
var root = $(document.getElementsByTagName('html')); | |
var watchers = []; | |
var attributes = []; | |
var attributes_with_values = []; | |
var elements = []; | |
var elements_per_attr = []; | |
var scopes = []; | |
function include(arr, obj) { | |
return (arr.indexOf(obj) != -1); | |
} | |
function is_not_duplicate(arr, obj) { | |
if (typeof arr == "undefined") { | |
return true; | |
} else { | |
if (include(arr, obj)) { | |
return false; | |
} else { | |
return true; | |
} | |
} | |
} | |
var f = function(element) { | |
if (element.data().hasOwnProperty('$scope')) { | |
if (typeof scopes[element.data().$scope.$id] == "undefined") { | |
scopes[element.data().$scope.$id] = true; | |
angular.forEach(element.data().$scope.$$watchers, function(watcher) { | |
watchers.push(watcher); | |
for (index = 0; index < element[0]['attributes'].length; ++index) { | |
if (is_not_duplicate(elements_per_attr[element[0]['attributes'][index].nodeName], element.data().$scope.$id)) { | |
if (typeof elements[element[0]['attributes'][index].nodeName] == "undefined") { | |
elements[element[0]['attributes'][index].nodeName] = []; | |
} | |
elements[element[0]['attributes'][index].nodeName].push({ | |
element: "(Scope " + element.data().$scope.$id + "): " + element[0].outerHTML, | |
element_obj: element[0], | |
element_data: element.data(), | |
relevant_watcher: watcher, | |
current_value: watcher.last | |
} | |
); | |
if (typeof elements_per_attr[element[0]['attributes'][index].nodeName] == "undefined") { | |
elements_per_attr[element[0]['attributes'][index].nodeName] = []; | |
} | |
elements_per_attr[element[0]['attributes'][index].nodeName].push(element.data().$scope.$id); | |
} | |
} | |
}); | |
} | |
} | |
angular.forEach(element.children(), function(childElement) { | |
f($(childElement)); | |
}); | |
}; | |
f(root); | |
console.log("####################"); | |
console.log("Analysing Watchers"); | |
console.log("####################"); | |
console.log(" "); | |
console.log("Watchers:"); | |
console.log(watchers.length); | |
console.log("----------------------------------------------"); | |
console.log("Watched Elements grouped by attribute"); | |
console.log(elements); | |
})(); |
Awesome. It helped me.
Notice the index
in the for
loop leaks to global context.
Great bookmarklet, thx !
Indeed however, the count is off by a large amount in component based applications. I just tried it on a page of an app Im working on, and the bklet misses a good third of the watchers given by :
angular.element('html').scope().$$watchersCount
Given that this line returns something like 900 watchers on an heavy page, yours gives me ~600 !
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for the gist.
It doesn't count watchers on isolate scope's. I guess this makes lot of difference where apps are component based.
element.scope() will never return the isolate scope anymore.
isolateScope() - retrieves an isolate scope if one is attached directly to the current element. This getter should be used only on elements that contain a directive which starts a new isolate scope. Calling scope() on this element always returns the original non-isolate scope.