Angularjs Factory值不会在多个视图中更新

时间:2016-01-31 16:08:34

标签: angularjs

我有这个简单的factory来从数据库中获取产品列表,并且如果产品是否是最喜欢的(基于用户交互),也可以切换。

function factoryProduct($http,$filter) {
    var data = {};
        data.list = [];

    var service = {
        getData:    _getData,
        toggleFav:  _toggleFav
    };
    return service;

    function _getData() {
        return $http.get('my/url/get.php').then(function(res){
            data.list = res;
            return res;
        });
    };
    function _toggleFav(value) {
        /* data manipulation here... */
        return $http.post('my/url/post.php', data).then(function(res){
            if (res==1) {
                return $filter('filter')(data.list)[index].inFav = value;
            };
        };
    };
}

这用于多个视图,例如主页,类别页面,收藏夹列表,心愿单等等。因此它在多个控制器中使用,我注入工厂然后将数据传递给视图

切换功能,因为它是相同的,它在指令中调用,但也很简单,如下所示:

scope.toggleFav = function(data, index) {
    /*data verification here*/
    factoryProduct.toggleFav(value);
}

在控制器中,像这样:

function MainCtrl(factoryProduct) {
    var vm = this;
    factoryProduct.getData().then(function(res){
        vm.list = res;
    })
}
function CategoryCtrl(factoryProduct) {
    var vm = this;
    /* category taken from url parameter */
    factoryProduct.getData().then(function(res){
        $filter('filter')(res, {category: urlParam});
        vm.list = res;
    })
}

我可以正确获取数据,制作过滤器并在每个视图上显示正确的产品列表。我也可以切换收藏夹,过滤器和数据库都可以正确更新。

问题

当我需要更改视图时,问题就开始了。例如:

如果我在主页上,将产品设置为收藏,转到联系页面然后返回主页,我刚刚设置为收藏的产品现在为非喜欢& #39; item,即使它是数据库中的最爱,也是在进入联系页面之前更新的。

我用这个:

var data = {};
    data.list = [];

因为我看到许多答案说要有一个静态数组并只操纵这个数组中的数据。但它不适合我。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

在页面生命周期内,有多种方法可以在工厂中设置存储数据。

在路由器中使用resolve对填充数据存储非常有帮助。然后当控制器触发时,数据已经存在。

另一个是检查数据是否存在以及是否确实返回$q.resolve(data)。 如果它不存在,则返回首先存储数据的$http承诺,然后返回存储的对象引用。

如果应用程序的许多部分在单个请求完成之前可能会要求相同的数据,那么我最近刚接受的另一个很有帮助。

您可以存储最初的承诺。您可以在应用生命周期内随时使用then()该承诺

app.factory('Factory', function($http){

  var dataPromise=null,  data=null;

  function getData() {
    if (!dataPromise) {
      console.warn('NEW REQUEST BEING MADE')
      dataPromise = $http.get('data.json').then(function(resp) {
        // store the data
        data = resp.data
        // return data stored in factory
        return data;
      })
    }else{
      console.info('Existing promise being returned')
    }
    return dataPromise;
  }

  return {
    getData: getData
  }   

});

如果第一个请求尚未完成,最后一种方法将阻止2个应用程序同时发出2个请求

$resource使用的最后一种方法是返回存储在工厂中的空对象。然后,当请求完成时,它们将数据合并到该对象中,而不会破坏原始对象引用。然后,当该对象直接传递给视图时,角度观察者将捕获更改并进行更新

DEMO