使用缓存的$ http响应不会发生摘要

时间:2014-09-18 18:21:01

标签: angularjs

使用angularjs 1.2.21

当我不使用带有$ http的缓存时,GET和异步响应之间显然存在摘要周期,因为在更改为插值变量后,我的页面中的可视元素已正确更新在视图中。 但是当我将缓存设置为true并且数据来自缓存时,我的视图停止更新,这意味着没有发生摘要。

angularjs doc声明即使数据来自缓存,响应也是异步的。但它没有提及消化周期。

  

请注意,即使响应是从缓存提供的,数据的传递也是异步的,就像实际请求一样。

要解决这个问题,我需要将$ http调用放在$ timeout(func,0)中。

那么,在您看来,这是一个错误还是它的设计?

更新:@ PSL I forked your plunk向您展示如何重现它。运行。您将看到"正在加载"第一次按下按钮时出现消息,然后它就不再出现了。删除缓存,它将每次出现。基本上我只是在Get Call中尝试改变视图,并在它完成时恢复它。

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.2.x" src="https://code.angularjs.org/1.2.21/angular.js" data-semver="1.2.22"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <p ng-show="load">Load in progress</p>
    <p>{{i}}</p>
    <button ng-click="refresh()">Refresh</button>
  </body>

</html>



var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, $http) {
  $scope.name = 'World';
  $scope.i=0;
  $scope.load = false;

  $scope.refresh = function(){
    $scope.load = true;
  $http.get('test.json', {cache:true}).success(function(resp){
    $scope.i++;
    $scope.name = resp;
    $scope.load = false;
  });
  }
});

更新2 :我不认为我可以在这里重现它,因为我的实际代码更复杂。实际上,修改load变量是由另一个指令(绑定到它)捕获的,它将重置第三方jquery模块。当使用缓存时,jquery模块并不总是正确地重置,这往往表明获得响应的速度太快,以至于绑定没有到达监视它的模块......

1 个答案:

答案 0 :(得分:1)

查看下面github上的角度done()函数,我认为这是一个错误。 (编辑 @PSL认为这不是一个错误)。

然而,仍然如此,假设此方法中没有出现错误,则无法避免使用scope.apply() - 除$apply.$$phase之外的其他错误。

也许最好的办法是使用useApplyAsync标志来确保它有效。

此处完成功能:

 function done(status, response, headersString, statusText) {
    if (cache) {
      if (isSuccess(status)) {
        cache.put(url, [status, response, parseHeaders(headersString), statusText]);
      } else {
        // remove promise from the cache
        cache.remove(url);
      }
    }

    function resolveHttpPromise() {
      resolvePromise(response, status, headersString, statusText);
    }

    if (useApplyAsync) {
      $rootScope.$applyAsync(resolveHttpPromise);
    } else {
      resolveHttpPromise();
      if (!$rootScope.$$phase) $rootScope.$apply();
    }
  }

实际上,在git 1.2.x分支上,useApplyAsync不可用。你能升级到最新版本吗?

旧的功能:

function done(status, response, headersString, statusText) {
    if (cache) {
      if (isSuccess(status)) {
        cache.put(url, [status, response, parseHeaders(headersString), statusText]);
      } else {
        // remove promise from the cache
        cache.remove(url);
      }
    }

    resolvePromise(response, status, headersString, statusText);
    if (!$rootScope.$$phase) $rootScope.$apply();
  }