diff options
| author | Igor Minar | 2011-11-30 14:47:28 -0500 | 
|---|---|---|
| committer | Igor Minar | 2011-11-30 14:49:36 -0500 | 
| commit | 1d14760c6d3eefb676f5670bc323b2a7cadcdbfa (patch) | |
| tree | 48c120bdde57ed7200ee53014781ca778b2f96ef /src | |
| parent | baa7af0df099fd4bfabe1e90d275822d2558d69c (diff) | |
| download | angular.js-1d14760c6d3eefb676f5670bc323b2a7cadcdbfa.tar.bz2 | |
fix(ng:include): prevent race conditions by ignoring stale http callbacks
This fix is similar to what I've done in ng:view, if a new template has been requested before the
callback for the previous template returned, ignore it. Otherwise weird race conditions happen
and users might end up getting the content for the previous include rendered instead of the most
recent one.
Diffstat (limited to 'src')
| -rw-r--r-- | src/widgets.js | 49 | 
1 files changed, 24 insertions, 25 deletions
| diff --git a/src/widgets.js b/src/widgets.js index 618de04d..155b8c08 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -94,42 +94,38 @@ angularWidget('ng:include', function(element){      function($http,   $templateCache,   $autoScroll,   element) {        var scope = this,            changeCounter = 0, -          releaseScopes = [], -          childScope, -          oldScope; +          childScope;        function incrementChange() { changeCounter++;}        this.$watch(srcExp, incrementChange); -      this.$watch(function(scope){ -        var newScope = scope.$eval(scopeExp); -        if (newScope !== oldScope) { -          oldScope = newScope; -          incrementChange(); -        } -      }); -      this.$watch(function() {return changeCounter;}, function(scope) { +      this.$watch(function() { +        var includeScope = scope.$eval(scopeExp); +        if (includeScope) return includeScope.$id; +      }, incrementChange); +      this.$watch(function() {return changeCounter;}, function(scope, newChangeCounter) {          var src = scope.$eval(srcExp),              useScope = scope.$eval(scopeExp);          function clearContent() { -          childScope = null; -          element.html(''); +          // if this callback is still desired +          if (newChangeCounter === changeCounter) { +            if (childScope) childScope.$destroy(); +            childScope = null; +            element.html(''); +          }          } -        while(releaseScopes.length) { -          releaseScopes.pop().$destroy(); -        }          if (src) {            $http.get(src, {cache: $templateCache}).success(function(response) { -            element.html(response); -            if (useScope) { -              childScope = useScope; -            } else { -              releaseScopes.push(childScope = scope.$new()); +            // if this callback is still desired +            if (newChangeCounter === changeCounter) { +              element.html(response); +              if (childScope) childScope.$destroy(); +              childScope = useScope ? useScope : scope.$new(); +              compiler.compile(element)(childScope); +              $autoScroll(); +              scope.$eval(onloadExp);              } -            compiler.compile(element)(childScope); -            $autoScroll(); -            scope.$eval(onloadExp);            }).error(clearContent);          } else {            clearContent(); @@ -574,7 +570,10 @@ angularWidget('ng:view', function(element) {          var template = $route.current && $route.current.template;          function clearContent() { -          element.html(''); +          // ignore callback if another route change occured since +          if (newChangeCounter == changeCounter) { +            element.html(''); +          }          }          if (template) { | 
