2015-08-13 59 views
2

有一件事我無法在Angular中理解 - 如何更好地將API數據與本地數據同步。ANgularJS根據請求提供本地數據的同步服務器數據

我的結構對象很大,我只是給你簡單的例子。

我有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中是否有任何數據。如果存在,我不發送請求。

但是,如果我從轎車頁面開始,我只接受轎車。然後,當我轉到常見頁面時 - 如何檢查我是否需要加載更多類別。

這是一個快速抽象的例子。但我試圖找到任何好的解決方案或插件,不能。

請幫幫我!

UPDATE:

這裏是我廠:

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

您需要爲此創建服務/工廠,而不是使用$ 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調用。

+0

是的,我使用工廠的所有API請求。爲什麼使用rootcope不好主意。我這樣做是爲了觀看。每個觀察$ rootScope.api的控制器都會更改並重新呈現新數據。例如,我有對象{a:1,b:2}。該對象在一些頁面中呈現。更新後我做angular.merge。恩。 {A:3。 C:4}。 $ rootScope.api變爲{a:3,b:2,c:4} 所有數據將自動重新呈現。有沒有辦法與cacheFactory做到這一點? –

+0

基本上它污染了$ rootScope(我不確定它在測試中的表現如何)。這就像全局變量 - 有時使用它更容易,但通常被認爲是不好的做法。在這種情況下,我沒有看到爲什麼不使用工廠而不是$ rootScope並處理所有緩存/更新的原因。你可以更具體的使用你的用例嗎? –

+0

我用我的工廠和控制器更新了我的帖子 –

相關問題