fix(ngView): use animation promises ensure that only one leave animation occurs at a time

the tracking depended on a local flag variable, which was susceptible to corruption due to
race conditions.

using promises ensures that the previousLeaveAnimation is nulled out only if it hasn't been
canceled yet.

Closes #9355
Closes #7606
Closes #9374
This commit is contained in:
Igor Minar
2014-10-01 14:57:32 -07:00
parent b1ee5386d5
commit 3624e3800f
2 changed files with 12 additions and 21 deletions

View File

@@ -188,7 +188,7 @@ function ngViewFactory( $route, $anchorScroll, $animate) {
link: function(scope, $element, attr, ctrl, $transclude) {
var currentScope,
currentElement,
previousElement,
previousLeaveAnimation,
autoScrollExp = attr.autoscroll,
onloadExp = attr.onload || '';
@@ -196,19 +196,20 @@ function ngViewFactory( $route, $anchorScroll, $animate) {
update();
function cleanupLastView() {
if(previousElement) {
previousElement.remove();
previousElement = null;
if(previousLeaveAnimation) {
$animate.cancel(previousLeaveAnimation);
previousLeaveAnimation = null;
}
if(currentScope) {
currentScope.$destroy();
currentScope = null;
}
if(currentElement) {
$animate.leave(currentElement).then(function() {
previousElement = null;
previousLeaveAnimation = $animate.leave(currentElement);
previousLeaveAnimation.then(function() {
previousLeaveAnimation = null;
});
previousElement = currentElement;
currentElement = null;
}
}

View File

@@ -845,18 +845,8 @@ describe('ngView animations', function() {
});
});
it('should destroy the previous leave animation if a new one takes place', function() {
module(function($provide) {
$provide.decorator('$animate', function($delegate, $$q) {
var emptyPromise = $$q.defer().promise;
$delegate.leave = function() {
return emptyPromise;
};
return $delegate;
});
});
inject(function ($compile, $rootScope, $animate, $location) {
var item;
it('should destroy the previous leave animation if a new one takes place',
inject(function ($compile, $rootScope, $animate, $location, $timeout) {
var $scope = $rootScope.$new();
element = $compile(html(
'<div>' +
@@ -884,8 +874,8 @@ describe('ngView animations', function() {
$rootScope.$digest();
expect(destroyed).toBe(true);
});
});
})
);
});