Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit f288b8f

Browse files
matskoIgorMinar
authored andcommitted
pref($animate): group all asynchronous requests into one shared buffer
1 parent b7e4e92 commit f288b8f

File tree

2 files changed

+59
-20
lines changed

2 files changed

+59
-20
lines changed

src/ngAnimate/animate.js

+28-12
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,20 @@ angular.module('ngAnimate', ['ng'])
268268
};
269269
}])
270270

271+
.factory('$$asyncQueueBuffer', ['$timeout', function($timeout) {
272+
var timer, queue = [];
273+
return function(fn) {
274+
$timeout.cancel(timer);
275+
queue.push(fn);
276+
timer = $timeout(function() {
277+
for(var i = 0; i < queue.length; i++) {
278+
queue[i]();
279+
}
280+
queue = [];
281+
}, 0, false);
282+
};
283+
}])
284+
271285
.config(['$provide', '$animateProvider', function($provide, $animateProvider) {
272286
var noop = angular.noop;
273287
var forEach = angular.forEach;
@@ -291,9 +305,10 @@ angular.module('ngAnimate', ['ng'])
291305
return extractElementNode(elm1) == extractElementNode(elm2);
292306
}
293307

294-
$provide.decorator('$animate', ['$delegate', '$injector', '$sniffer', '$rootElement', '$timeout', '$rootScope', '$document',
295-
function($delegate, $injector, $sniffer, $rootElement, $timeout, $rootScope, $document) {
308+
$provide.decorator('$animate', ['$delegate', '$injector', '$sniffer', '$rootElement', '$$asyncQueueBuffer', '$rootScope', '$document',
309+
function($delegate, $injector, $sniffer, $rootElement, $$asyncQueueBuffer, $rootScope, $document) {
296310

311+
var globalAnimationCounter = 0;
297312
$rootElement.data(NG_ANIMATE_STATE, rootAnimateState);
298313

299314
// disable animations during bootstrap, but once we bootstrapped, wait again
@@ -315,10 +330,6 @@ angular.module('ngAnimate', ['ng'])
315330
return classNameFilter.test(className);
316331
};
317332

318-
function async(fn) {
319-
return $timeout(fn, 0, false);
320-
}
321-
322333
function lookup(name) {
323334
if (name) {
324335
var matches = [],
@@ -685,7 +696,6 @@ angular.module('ngAnimate', ['ng'])
685696
if(ngAnimateState.running) {
686697
//if an animation is currently running on the element then lets take the steps
687698
//to cancel that animation and fire any required callbacks
688-
$timeout.cancel(ngAnimateState.closeAnimationTimeout);
689699
cleanup(element);
690700
cancelAnimations(ngAnimateState.animations);
691701

@@ -736,12 +746,15 @@ angular.module('ngAnimate', ['ng'])
736746
//parent animations to find and cancel child animations when needed
737747
element.addClass(NG_ANIMATE_CLASS_NAME);
738748

749+
var localAnimationCount = globalAnimationCounter++;
750+
739751
element.data(NG_ANIMATE_STATE, {
740752
running:true,
741753
event:animationEvent,
742754
className:className,
743755
structural:!isClassBased,
744756
animations:animations,
757+
index:localAnimationCount,
745758
done:onBeforeAnimationsComplete
746759
});
747760

@@ -816,19 +829,19 @@ angular.module('ngAnimate', ['ng'])
816829
}
817830

818831
function fireBeforeCallbackAsync() {
819-
async(function() {
832+
$$asyncQueueBuffer(function() {
820833
fireDOMCallback('before');
821834
});
822835
}
823836

824837
function fireAfterCallbackAsync() {
825-
async(function() {
838+
$$asyncQueueBuffer(function() {
826839
fireDOMCallback('after');
827840
});
828841
}
829842

830843
function fireDoneCallbackAsync() {
831-
async(function() {
844+
$$asyncQueueBuffer(function() {
832845
fireDOMCallback('close');
833846
doneCallback && doneCallback();
834847
});
@@ -855,8 +868,11 @@ angular.module('ngAnimate', ['ng'])
855868
if(isClassBased) {
856869
cleanup(element);
857870
} else {
858-
data.closeAnimationTimeout = async(function() {
859-
cleanup(element);
871+
$$asyncQueueBuffer(function() {
872+
var data = element.data(NG_ANIMATE_STATE) || {};
873+
if(localAnimationCount == data.index) {
874+
cleanup(element);
875+
}
860876
});
861877
element.data(NG_ANIMATE_STATE, data);
862878
}

test/ngAnimate/animateSpec.js

+31-8
Original file line numberDiff line numberDiff line change
@@ -2563,8 +2563,9 @@ describe("ngAnimate", function() {
25632563
});
25642564

25652565

2566-
it("should disable all child animations on structural animations until the post animation timeout has passed", function() {
2567-
var intercepted;
2566+
it("should disable all child animations on structural animations until the post animation" +
2567+
"timeout has passed as well as all structural animations", function() {
2568+
var intercepted, continueAnimation;
25682569
module(function($animateProvider) {
25692570
$animateProvider.register('.animated', function() {
25702571
return {
@@ -2578,7 +2579,10 @@ describe("ngAnimate", function() {
25782579
function ani(type) {
25792580
return function(element, className, done) {
25802581
intercepted = type;
2581-
(done || className)();
2582+
continueAnimation = function() {
2583+
continueAnimation = angular.noop;
2584+
(done || className)();
2585+
}
25822586
}
25832587
}
25842588
});
@@ -2595,26 +2599,45 @@ describe("ngAnimate", function() {
25952599
var child2 = $compile('<div class="child2 animated">...</div>')($rootScope);
25962600
var container = $compile('<div class="container">...</div>')($rootScope);
25972601

2598-
jqLite($document[0].body).append($rootElement);
2602+
var body = angular.element($document[0].body);
2603+
body.append($rootElement);
25992604
$rootElement.append(container);
26002605
element.append(child1);
26012606
element.append(child2);
26022607

2603-
$animate.move(element, null, container);
2608+
$animate.enter(element, container);
26042609
$rootScope.$digest();
26052610

2606-
expect(intercepted).toBe('move');
2611+
expect(intercepted).toBe('enter');
2612+
continueAnimation();
26072613

26082614
$animate.addClass(child1, 'test');
26092615
expect(child1.hasClass('test')).toBe(true);
26102616

2611-
expect(intercepted).toBe('move');
2617+
expect(element.children().length).toBe(2);
2618+
2619+
expect(intercepted).toBe('enter');
26122620
$animate.leave(child1);
26132621
$rootScope.$digest();
26142622

2623+
expect(element.children().length).toBe(1);
2624+
2625+
expect(intercepted).toBe('enter');
2626+
2627+
$animate.move(element, null, container);
2628+
$rootScope.$digest();
2629+
26152630
expect(intercepted).toBe('move');
26162631

2617-
//reflow has passed
2632+
//flush the enter reflow
2633+
$timeout.flush();
2634+
2635+
$animate.addClass(child2, 'testing');
2636+
expect(intercepted).toBe('move');
2637+
2638+
continueAnimation();
2639+
2640+
//flush the move reflow
26182641
$timeout.flush();
26192642

26202643
$animate.leave(child2);

0 commit comments

Comments
 (0)