aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Minar2011-10-26 12:15:07 -0700
committerIgor Minar2011-10-26 12:15:07 -0700
commitd5ccabce600efb10092fdf0ae033c009026bf4cb (patch)
tree3debd4dfe43213252b685ec7fa76459c5337bc9b
parentbb948176aaf6748c0d27772797b4c1490612b917 (diff)
downloadangular.js-d5ccabce600efb10092fdf0ae033c009026bf4cb.tar.bz2
fix(ng:view): ignore stale xhr callbacks
A lot of badness happens when we don't ignore stale xhrs. These raceconditions are only apparent when user clicks through the app very quckly without waiting for routes to fully load. Closes #619
-rw-r--r--src/widgets.js9
-rw-r--r--test/widgetsSpec.js20
2 files changed, 26 insertions, 3 deletions
diff --git a/src/widgets.js b/src/widgets.js
index 423fe6dd..c70e9efa 100644
--- a/src/widgets.js
+++ b/src/widgets.js
@@ -551,13 +551,16 @@ angularWidget('ng:view', function(element) {
changeCounter++;
});
- this.$watch(function() {return changeCounter;}, function() {
+ this.$watch(function() {return changeCounter;}, function(scope, newChangeCounter) {
var template = $route.current && $route.current.template;
if (template) {
//xhr's callback must be async, see commit history for more info
$xhr('GET', template, function(code, response) {
- element.html(response);
- compiler.compile(element)($route.current.scope);
+ // ignore callback if another route change occured since
+ if (newChangeCounter == changeCounter) {
+ element.html(response);
+ compiler.compile(element)($route.current.scope);
+ }
});
} else {
element.html('');
diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js
index adbdf94e..4aa36428 100644
--- a/test/widgetsSpec.js
+++ b/test/widgetsSpec.js
@@ -539,6 +539,26 @@ describe("widget", function() {
expect(rootScope.log).toEqual(['parent', 'init', 'child']);
});
+
+ it('should discard pending xhr callbacks if a new route is requested before the current ' +
+ 'finished loading', function() {
+ // this is a test for a bad race condition that affected feedback
+
+ $route.when('/foo', {template: 'myUrl1'});
+ $route.when('/bar', {template: 'myUrl2'});
+
+ expect(rootScope.$element.text()).toEqual('');
+
+ $location.path('/foo');
+ $browser.xhr.expectGET('myUrl1').respond('<div>{{1+3}}</div>');
+ rootScope.$digest();
+ $location.path('/bar');
+ $browser.xhr.expectGET('myUrl2').respond('<div>{{1+1}}</div>');
+ rootScope.$digest();
+ $browser.xhr.flush(); // no that we have to requests pending, flush!
+
+ expect(rootScope.$element.text()).toEqual('2');
+ });
});