ANgularJS根据请求同步服务器数据和本地数据

时间:2015-08-13 07:07:57

标签: angularjs api rest

在Angular中有一件我无法理解的事情 - 如何更好地将API数据与本地数据同步。

我的结构对象非常大,我只举几个例子。

我有4个api链接。

api_links: {
  allCars: '/cars/',
     cabrio: '/cars/cabrio',
     sedan: '/cars/sedan',
        mercedes: 'cars/sedan/mercedes'
}

这是我本地保存数据的本地对象

$rootScope.apiData = {
  cars{
    cabrio:{},
    sedan: {}
  }
}

在我的单页应用中,我希望减少请求数。 因此,在常见页面上,我收到所有汽车并将数据放入$ rootScope.apiData

当我进入轿车页面时,我会检查$ rootScope.apiData.cars.sedan中是否有任何数据。如果它存在,我不发送请求。

但如果我从轿车页面开始,我只收到轿车。然后,当我进入公共页面 - 如何检查我是否需要加载更多类别。

这是一个快速抽象的例子。但我试图为此找到任何好的解决方案或插件,但不能。

请帮助我!

更新:

这是我的工厂:

var api = angular.module('app.api', []);
api.factory('GetData', ['$http', '$q', '$rootScope', '$location'
    function($http, $q, $rootScope, $location) {


        var apiUrl = '/api/js/';
        var apiMixes = {
            dashBoard: 'api/dashboard',
            accounts: 'api/accounts',
            top: 'top',
            logout: 'client/logout',
            ...
        }

        var methods = {};

        methods.getApi = function(u, params) {

            var url = apiMixes[u] + '?' + $.param( params );

            var deferred = $q.defer();



            // Here I need to check if I have cached data
            cachedData(data) = ___TODO___;

            if( cachedData(data) ){

                deferred.resolve(cachedData(data));

                // Turn watching on
                $rootScope.$emit("receivedApiUpdate", cachedData(data));

                return deferred.promise;

            }


            // If no - get gata from server and put to cache
            $http.get(url, {cache: true}).success(function (res, status, headers, config) {

                if(res && res.data){

                    // Turn watching on
                    $rootScope.$emit("receivedApiUpdate", res.data);

                    //LocalData.put(res.data);
                    deferred.resolve(res.data);

                }else{

                    deferred.reject(status);

                }



            }).error(function (res, status, headers, config) {

                (status==401) && $location.path('login/lock');

                deferred.reject(status);
            });

            return deferred.promise;



        };



        methods.sendData = function(u, data, o) {

            data = data || {};
            o = o || {};

            var deferred = $q.defer();

            var url = '/api/js/'+ apiMixes[u];


            $http.post(url, JSON.stringify(data)).success(function(res, status) {


                if(res.success && res.data){


                    // Here I need to update my cache with some new value
                    o.localUpdate && ___PUT_TO_CACHE_TODO___;

                    deferred.resolve(res.data);


                }


            });

            return deferred.promise;
        };


        return methods;


}]);

这是我的控制器

app.controller('MyAccountsCtrl', ["$rootScope", "$scope", 
    function ($rootScope, $scope) {


    // Watcher for api updates
    $rootScope.$on('receivedApiUpdate',function(event, response){

        if(!response || !response.accounts) return;
        renderData(response.accounts);

    });


    function renderData(accounts){

        // This renders to template
        $scope.accountList = accounts;

    }


}]);

这是mainCtrl,whick做出常见请求,之后我需要更新几个模板中的数据。

app.controller('AppCtrl', ['$rootScope', '$scope', 'GetData',
function ($rootScope, $scope, GetData) {

    // Here I fire different request for each page, I keep requests in router.
    GetData.getApi( 'accounts' ).then(function(data){

        // Show content when page is loaded
        $('.main-content').removeClass('hidden');

    },function(res){
        log('GET DATA FAIL', res);

    });


}]);

1 个答案:

答案 0 :(得分:1)

您需要为此创建服务/工厂,而不是使用$ rootScope。此外,除非您需要不断更新数据,否则您可以使用$ http调用中的cache: true选项。

angular
    .module('app')
        .factory('carFactory', carFactory);

function carFactory() {
    var factory = {
        getData: getData
    }

    return factory;

    function getData(callback) {
        $http({
            method: 'GET',
            url: '/cars',
            cache: true
        }).success(callback);
    }
}

然后在您的控制器/指令内部注入carFactory并在需要数据时使用carFactory.getData(function(cars) { ... })。如果数据不存在,它将为$ http调用它,然后执行回调函数。如果它确实存在,它将直接将数据返回给回调,而不需要$ http调用。