{"action":"created","issue":{"url":"https://api.github.com/repos/angular/angular.js/issues/10506","labels_url":"https://api.github.com/repos/angular/angular.js/issues/10506/labels{/name}","comments_url":"https://api.github.com/repos/angular/angular.js/issues/10506/comments","events_url":"https://api.github.com/repos/angular/angular.js/issues/10506/events","html_url":"https://github.com/angular/angular.js/issues/10506","id":52269264,"number":10506,"title":"$animate service requests unnecessary animation frames","user":{"login":"dmcquillan314","id":2671966,"avatar_url":"https://avatars.githubusercontent.com/u/2671966?v=3","gravatar_id":"","url":"https://api.github.com/users/dmcquillan314","html_url":"https://github.com/dmcquillan314","followers_url":"https://api.github.com/users/dmcquillan314/followers","following_url":"https://api.github.com/users/dmcquillan314/following{/other_user}","gists_url":"https://api.github.com/users/dmcquillan314/gists{/gist_id}","starred_url":"https://api.github.com/users/dmcquillan314/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dmcquillan314/subscriptions","organizations_url":"https://api.github.com/users/dmcquillan314/orgs","repos_url":"https://api.github.com/users/dmcquillan314/repos","events_url":"https://api.github.com/users/dmcquillan314/events{/privacy}","received_events_url":"https://api.github.com/users/dmcquillan314/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/angular/angular.js/labels/component:%20ngAnimate","name":"component: ngAnimate","color":"bfdadc"},{"url":"https://api.github.com/repos/angular/angular.js/labels/needs:%20investigation","name":"needs: investigation","color":"444444"}],"state":"open","locked":false,"assignee":{"login":"matsko","id":93018,"avatar_url":"https://avatars.githubusercontent.com/u/93018?v=3","gravatar_id":"","url":"https://api.github.com/users/matsko","html_url":"https://github.com/matsko","followers_url":"https://api.github.com/users/matsko/followers","following_url":"https://api.github.com/users/matsko/following{/other_user}","gists_url":"https://api.github.com/users/matsko/gists{/gist_id}","starred_url":"https://api.github.com/users/matsko/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matsko/subscriptions","organizations_url":"https://api.github.com/users/matsko/orgs","repos_url":"https://api.github.com/users/matsko/repos","events_url":"https://api.github.com/users/matsko/events{/privacy}","received_events_url":"https://api.github.com/users/matsko/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/angular/angular.js/milestones/27","html_url":"https://github.com/angular/angular.js/milestones/Backlog","labels_url":"https://api.github.com/repos/angular/angular.js/milestones/27/labels","id":489171,"number":27,"title":"Backlog","description":"Holds the backlog of issues and pull requests that have been triaged.\r\n\r\nBefore assigning items to this milestone they should be labelled, at the very least with the correct \"type\" label (i.e. \"issue\", \"pr\", \"bug\", \"regression\", \"chore\", \"docs\", etc).  Preferably you should also check for duplicate issues/PRs, note CLA status and assign \"complexity\" and \"impact\" labels too.","creator":{"login":"IgorMinar","id":216296,"avatar_url":"https://avatars.githubusercontent.com/u/216296?v=3","gravatar_id":"","url":"https://api.github.com/users/IgorMinar","html_url":"https://github.com/IgorMinar","followers_url":"https://api.github.com/users/IgorMinar/followers","following_url":"https://api.github.com/users/IgorMinar/following{/other_user}","gists_url":"https://api.github.com/users/IgorMinar/gists{/gist_id}","starred_url":"https://api.github.com/users/IgorMinar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IgorMinar/subscriptions","organizations_url":"https://api.github.com/users/IgorMinar/orgs","repos_url":"https://api.github.com/users/IgorMinar/repos","events_url":"https://api.github.com/users/IgorMinar/events{/privacy}","received_events_url":"https://api.github.com/users/IgorMinar/received_events","type":"User","site_admin":false},"open_issues":732,"closed_issues":772,"state":"open","created_at":"2013-11-18T23:30:35Z","updated_at":"2015-03-05T14:54:19Z","due_on":null,"closed_at":null},"comments":3,"created_at":"2014-12-17T17:42:32Z","updated_at":"2015-03-06T19:37:55Z","closed_at":null,"body":"I'm creating a large collection of product-like objects and am noticing multiple performance issues when using a combination of ng-animate and any ng-* directive that has interaction with the $animate service. \r\n\r\nWhen inspecting the performance of the application on load of product cells I'm noticing a significant drop in performance when I have the ngAnimate module included:\r\n![screen shot 2014-12-17 at 11 29 14 am](https://cloud.githubusercontent.com/assets/2671966/5475604/114bdf36-85e0-11e4-8c34-f9a50213e713.png)\r\n\r\nOn average for a collection of ~100 products loading at once this seems to be adding ~200ms to the load of the page.\r\n\r\nBased on the angularJS documentation we should be able to do something like the following to disable animations on an element:\r\n        ```\r\n       $animateProvider.classNameFilter(/^(?!.*disable\\-animations).*$/i);\r\n       ```\r\n\r\nwhich would disable the animations on an element such as this:\r\n        ```\r\n        <div class=\"some-element disable-animations\" ng-if=\"condition\">show/hide me</div>\r\n        ```\r\n\r\nHowever when I inspect the application I do see that the animate module disables the animation but it does not disable the request for an animation frame which is causing issues.  \r\n\r\nFrom a bit a research into the animate module this seems to be the offending piece of code:\r\n        ```\r\n        //skip the animation if animations are disabled, a parent is already being animated,\r\n        //the element is not currently attached to the document body or then completely close\r\n        //the animation if any matching animations are not found at all.\r\n        //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case an animation was found.\r\n        if (animationsDisabled(element, parentElement)) {\r\n          fireDOMOperation();\r\n          fireBeforeCallbackAsync();\r\n          fireAfterCallbackAsync();\r\n          closeAnimation();\r\n          return noopCancel;\r\n        }\r\n        ```\r\n"},"comment":{"url":"https://api.github.com/repos/angular/angular.js/issues/comments/77621655","html_url":"https://github.com/angular/angular.js/issues/10506#issuecomment-77621655","issue_url":"https://api.github.com/repos/angular/angular.js/issues/10506","id":77621655,"user":{"login":"dmcquillan314","id":2671966,"avatar_url":"https://avatars.githubusercontent.com/u/2671966?v=3","gravatar_id":"","url":"https://api.github.com/users/dmcquillan314","html_url":"https://github.com/dmcquillan314","followers_url":"https://api.github.com/users/dmcquillan314/followers","following_url":"https://api.github.com/users/dmcquillan314/following{/other_user}","gists_url":"https://api.github.com/users/dmcquillan314/gists{/gist_id}","starred_url":"https://api.github.com/users/dmcquillan314/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dmcquillan314/subscriptions","organizations_url":"https://api.github.com/users/dmcquillan314/orgs","repos_url":"https://api.github.com/users/dmcquillan314/repos","events_url":"https://api.github.com/users/dmcquillan314/events{/privacy}","received_events_url":"https://api.github.com/users/dmcquillan314/received_events","type":"User","site_admin":false},"created_at":"2015-03-06T19:37:55Z","updated_at":"2015-03-06T19:37:55Z","body":"After doing a bit more research on this issue I discovered that the issue has to do with the $$AsyncCallbackProvider:\r\n\r\n``` js\r\nfunction $$AsyncCallbackProvider() {\r\n  this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {\r\n    return $$rAF.supported\r\n      ? function(fn) { return $$rAF(fn); }\r\n      : function(fn) {\r\n        return $timeout(fn, 0, false);\r\n      };\r\n  }];\r\n}\r\n```\r\n\r\nThis is a problem since when the animations are \"cancelled\" in this call (offending methods are commented:\r\n``` js\r\n        if (!runner) {\r\n          fireDOMOperation();\r\n          fireBeforeCallbackAsync(); // triggers request\r\n          fireAfterCallbackAsync(); // triggers request\r\n          closeAnimation();\r\n          return noopCancel;\r\n        }\r\n```\r\nwhich is supposedly set up to cancel an animation but however the fireDOMCallback(animationPhase) method:\r\n``` js\r\nfunction fireDOMCallback(animationPhase) {\r\n          var eventName = '$animate:' + animationPhase;\r\n          if (elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) {\r\n            $$asyncCallback(function() {\r\n              element.triggerHandler(eventName, {\r\n                event: animationEvent,\r\n                className: className\r\n              });\r\n            });\r\n          }\r\n        }\r\n```\r\nmakes a call to the $$asyncCallback even when the animations have been disabled which transitively triggers the request for an unnecessary animation frame.  \r\n\r\nA simple fix could be something as simple as checking to see if the animation was disabled before making the call to the asyncCallback method.  Or possible parameterizing the $$asyncCallback to support a disableRAF property.  \r\n\r\nI'll keep doing more investigation and possibly open a PR shortly."}}