【问题标题】:Prevent AngularJS to return promise with cached data防止 AngularJS 返回带有缓存数据的承诺
【发布时间】:2013-08-22 17:08:54
【问题描述】:

我正在使用一项服务来在控制器之间共享数据。但是,即使在发出新请求时,该服务也会返回带有缓存数据的承诺。根据defer 实例的创建位置,要么返回实时数据但双向绑定中断,要么双向绑定有效但返回缓存数据。

如何防止带有缓存数据的承诺返回并保持双向绑定?

我已经放了一个plunker来说明这个案例:http://plnkr.co/edit/SyBvUu?p=preview为了完整起见,这里是故障排除服务:

app.service('myService', function($http, $q) {

    // When instancing deferred here two way binding works but cached data is returned
    var deferred = $q.defer();

    this.get = function(userId) {
        // When instancing deferred here two way binding breaks but live data is returned
        //var deferred = $q.defer();

        console.log('Fetch data again using id ', userId);
        var url = userId + '.json';
        $http.get(url, {timeout: 30000, cache: false})
            .success(function(data, status, headers, config) {
                deferred.resolve(data, status, headers, config);
            })
            .error(function(data, status, headers, config) {
                deferred.reject(data, status, headers, config);
            });
        return deferred.promise;
    };

});

更新:问题不在于数据被缓存,而在于我不了解如何共享数据并且共享数据不能是原始数据。请参阅下面我自己的答案。

【问题讨论】:

  • 嗯,只是为了运动-如果你这样做var url = userId+".json?cacheBreaker="+Date.now();会发生吗?
  • 是的,我之前尝试过该路径,但无济于事。当请求不同的 json 文件时,返回的响应包含预期的用户数据。

标签: angularjs promise


【解决方案1】:

由于 $http 返回一个延迟对象,你在这里所做的实际上是矫枉过正。当我将您的服务更改为以下时,它似乎工作正常。

Plunker

app.service('myService', function($http, $q) {

    this.get = function(userId) {
        console.log('Fetch data again using id ', userId);
        var url = userId + '.json';

        return $http.get(url, {timeout: 30000, cache: false});
    };

});

编辑

要更新您的控制器SecondCtrl,最简单的方法是在保持代码结构相同的同时,使用$rootScope.$broadcastFirstCtrl 中定义的事件中广播新数据并捕获使用$scope.$on 在您的其他控制器中广播事件。我已经更新了 Plunker,现在你的数据已经同步了。

修改了FirstCtrl中的loadUserFromMyService函数:

$scope.loadUserFromMyService = function(userId) {
    var promise = myService.get(userId);
    promise.then(
      function(data) { 
        console.log('UserData', data);
        $scope.data = data;
        $rootScope.$broadcast('newData', data);  
      },
      function(reason) { console.log('Error: ' + reason); }
    );      
};

添加于SecondCtrl:

$scope.$on('newData', function (evt, args) {
  console.log('dataChanged', args);
  $scope.data = args;
});

【讨论】:

  • 嗨罗伊!不幸的是,这两个绑定不起作用。还是我遗漏了一些明显的东西?
  • 我认为您可能误解了数据绑定的工作原理。给我几分钟时间来更新我的答案,以便更详细地解释。
  • 嘿@JohnP,抱歉花了这么长时间。我已经更新了我的答案。现在您的数据已同步。
  • 感谢您的努力。在寻找答案时,我发现一个网站描述了在控制器之间共享数据的一些方法,而第三种选择似乎是可行的方法。它实际上与您提出的解决方案相同 - 使用广播等。 ramandv.com/blog/angular-js-sharing-data
  • 我想出了另一种解决方案,见下文,这样就不必使用 $broadcast 和 $on。感觉干净了一点。
【解决方案2】:

在 Luke Kende 的帮助下,我提出了共享数据的简化解决方案。这是一个笨蛋:http://plnkr.co/edit/JPg1XE?p=preview。请参阅下面的代码。

重要的一点是共享对象不是原始对象。当我尝试不同的解决方案时,我首先声明共享对象并分配它null,这是一个禁忌。使用空对象使其工作。

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

// Service
app.service('myService', function($http, $q) {

    //object that will be shared between controllers
    var serviceData = {
        items: []
    };

    return {
      data: serviceData, //pass through reference to object - do not use primitives else data won't update
      get: function(url, overwrite) {
          if (serviceData.items.length === 0 || overwrite){
              $http.get(url, {timeout: 30000})
                  .success(function(data, status, headers, config) {
                    //could extend instead of ovewritting
                    serviceData.items = data;
                  })
                  .error(function(data, status, headers, config) {
                      serviceData.items = {status: status};
                  });
          }
          return serviceData;
      },
      empty: function(){
          serviceData.items = [];
      },
      more: function(){
          //do some other operations on the data
      }
    };
});

// Controller 1
app.controller('FirstCtrl', function( myService,$scope) {

    //myService.data is not initialized from server yet
    //this way don't have to always use .then() statements
    $scope.data = myService.data; 

    $scope.getTest = function(id){
        myService.get('test' + id + '.json',true);
    };
    $scope.addItem = function() {
        $scope.data.items.push({'title': 'Test ' + $scope.data.items.length});
    };
    $scope.delItem = function() {
        $scope.data.items.splice(0,1);
    };

});

// Controller 2
app.controller('SecondCtrl', function( myService,$scope) {

    //just attach myService.data and go
    //calling myService.get() results in same thing
    $scope.data = myService.data;

    //update the the data from second url -
    $scope.getTest = function(id){
        myService.get('test' + id + '.json',true);
    };

    $scope.empty = function(){
       myService.empty();
    };
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-09
    • 2015-08-29
    相关资源
    最近更新 更多