2013-08-21 1 views
2

Я использую услугу для обмена данными между контроллерами. Тем не менее, служба возвращает обещание с кэшированными данными даже при создании новых запросов. В зависимости от того, где создается экземпляр defer, возвращаются живые данные, но двусторонние перерывы привязки или двусторонняя привязка работают, но возвращаются кэшированные данные.Предотвращение отклонения выражения AngularJS с кэшированными данными

Как можно предотвратить возврат обещания с кешированными данными и сохранить двустороннюю привязку?

Я мириться 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; 
    }; 

}); 

UPDATE: Проблема не в том, что данные в кэше, это было что я не понял, как должны делиться данные и что общие данные не могут быть примитивными. См. Мой собственный ответ ниже.

+0

Хм, только для спорта - это происходит, если вы 'вар URL = USERID + + Date.now();' "JSON cacheBreaker =.?"? –

+0

Да, я пробовал этот путь раньше, но безрезультатно. При запросе на различные json-файлы возвращаемый ответ содержит ожидаемые пользовательские данные. –

ответ

3

Поскольку $ 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 обновлять, проще всего сделать, сохраняя при этом структуру кода же, должен транслировать новые данные событие, определенное в FirstCtrl с использованием $rootScope.$broadcast и захват передаваемого события в другом контроллере с помощью $scope.$on. Я обновил Plunker, и теперь ваши данные синхронизированы.

Модифицированный loadUserFromMyService функции в FirstCtrl:

$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; 
}); 
+0

Привет, Рой! К сожалению, двухсвязывание тогда не работает. Или я пропущу что-то очевидное? –

+0

Я думаю, вы можете не понимать, как работает привязка данных. Дайте мне несколько минут, чтобы обновить мой ответ, чтобы объяснить более подробно. –

+0

Эй, @ JohnP, извините, что так долго. Я обновил свой ответ. Теперь ваши данные синхронизированы. –

0

я придумал упрощенным решением для обмена данных с помощью Люка Кенда. Вот плунж: 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(); 
    }; 
});