AngularJS: управление данными сервисов с помощью factory

Я пытаюсь «контролировать» данные на фабрике с двух отдельных контроллеров, и хотя приведенный ниже код работает нормально, он не всегда работает. По какой-то причине он связывает данные только примерно в 50% случаев. Есть ли способ убедиться, что данные привязываются все время, и если какой-либо контроллер вносит изменения в данные, эти изменения будут отражены на обоих концах.

Обслуживание:

angular.module('service', ['ngResource']).
    factory('Service', function($resource){
        return $resource('/api/data/:id', {id:'@id'}, {});
});

Фабрика:

angular.module('factory', ['ngResource', 'service']).
    factory('Factory', function($resource, Service) {
        this.mydata = '';
        return {
            getData: function(id){
            return Service.query({id: id});
            },

            data: function(data){
            return this.mydata;
            },

            setData: function(data){
            this.mydata = data;
            }
        }
});

Контроллер:

$scope.Factory = Factory;
var items = Factory.getData(0);

items.$promise.then(function(itemArr){

    var item = itemArr[0];
    $scope.data = item;

    Factory.setData(item);
});

Если есть лучший способ сделать это, чтобы мне не нужно было устанавливать данные на заводе, это было бы неплохо. Также было бы неплохо не иметь дело с объектом обещания в контроллере, но я не думаю, что было бы возможно получить данные на фабрике.

После настройки данных с использованием вышеуказанной фабрики я получаю к ним доступ в другом контроллере со следующим кодом:

    var item = Factory.data();
    $scope.selected = [{foo:'bar'},{foo1:'bar1'}];

    angular.forEach($scope.selected, function(value, key){
        item.requirements.push(value);
    })

    Factory.setData(item);

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

РЕДАКТИРОВАТЬ: я смог заставить его работать все время, используя функциональность $scope.$watch в контроллере для функции обратного вызова. Данные связаны, но angular должен знать, за чем следить, как это предлагается в ответе ниже.


person Ty Danielson    schedule 29.08.2013    source источник


Ответы (1)


Чтобы не нужно было вручную устанавливать данные в «фабрике» (он же сервис angular), вы можете просто установить их в обратном вызове для ресурса:

 return {
            getData: function(id){
              return Service.query({id: id}, function(data){
                myData = data;
              });
            },

Если вы не хотите иметь дело с объектом обещания, вы можете отправить собственный обратный вызов в функцию getData и, когда он будет завершен, вызвать обратный вызов, который вы отправляете в обратном вызове ресурса:

 return {
                getData: function(id, cb){
                  return Service.query({id: id}, function(data){
                    myData = data;
                    if (cb) {cb(data);}
                  });
                },

Что меняет способ вызова getData на это:

var items = Factory.getData(0, function(itemArr){
    var item = itemArr[0];
    $scope.data = item;
});
person BoxerBucks    schedule 29.08.2013
comment
Я переключил контроллер на использование обратного вызова, чтобы избежать использования объекта обещания, что действительно приятно. Однако я не могу установить this.mydata в обратном вызове функции getData. Ошибка проста в том, что она не определена, потому что я предполагаю, что она не входит в область действия. У вас есть идеи, как это установить? Я предполагаю, что это корень того, почему он работает только некоторое время. - person Ty Danielson; 29.08.2013
comment
Попробуйте потерять «это» и просто сослаться на myData. Объявите «var myData =» в сервисе Factory. - person BoxerBucks; 29.08.2013
comment
У меня такая же проблема, что она не определена. Я не уверен, почему эта переменная будет недоступна из обратного вызова успеха, но это не так. - person Ty Danielson; 29.08.2013
comment
О, я думаю, вы имеете в виду, что хотите, чтобы данные вернулись в обратный вызов Factory.getData? Я отредактировал ответ. - person BoxerBucks; 29.08.2013
comment
Я добавил еще немного к вопросу выше. Я отлично получаю данные, но все еще не могу установить данные в функции getData. Я должен вызвать setData, чтобы установить его, и, похоже, он работает только в 50% случаев. - person Ty Danielson; 29.08.2013
comment
Вам больше не нужно вызывать setData, поскольку он устанавливается в обратном вызове после завершения запроса. Если вы одновременно пытаетесь получить к нему доступ в параллельном контроллере, вам нужно настроить часы на Factory.data и, когда они изменятся, использовать их. - person BoxerBucks; 29.08.2013