在开发中,我们经常要访问接口来取一些不经常变化的数据,例如会员类型、产品分类等数据,频率的访问远程API而造成资源浪费,体验度差,所以想到用以下的方法来实现。
具体思路是通过http拦截,取API远程访问的方法名和参数,并将取回的数据缓存到本地,下次GET同一个API方法,且参数又相同,则直接使用本地缓存中的数据,而不去GET远程API接口。POST取数的方式还没有实现。
1、在.config节点注入拦截器
.config(function($stateProvider, $urlRouterProvider,$ionicConfigProvider,$httpProvider) {
})$httpProvider.interceptors.push('UserInterceptor');
2、声明拦截器代码
//数据缓存,//CacheDataService是我的一个数据缓存服务.factory('UserInterceptor', ["$q","$rootScope","$injector",function ($q,$rootScope,$injector,CacheDataService) { return { request:function(config){ //$rootScope.$broadcast('loading:show') return config; }, response:function(response){ var data=response.data; if (!data.success){ if (data.ResponseCode=="2003"){ //这里可以根据API接口的返回状态码来判断API访问时的TOKEN是否过期,可以根据自己的实际情况修改 window.location="#/tab/login" } }else{
//这里取远程访问API时的接口方法 var tmp= response.config.url.substr(response.config.url.indexOf('api'),response.config.url.indexOf('?')-response.config.url.indexOf('api'));
//获得GET方法时用到的参数,POST方法暂时没有做 var param=response.config.url.substr(response.config.url.indexOf('?')+1);
//获得CacheDataService服务 var CacheDataService= $injector.get("CacheDataService");
//检查该API方法名是否在缓存清单中 if (CacheDataService.CheckCanCache(tmp)) {
//开始缓存该数据 CacheDataService.CacheDataFactory(tmp,param,response.data); } } // $rootScope.$broadcast('loading:hide') return response }, responseError: function (response) { // $rootScope.$broadcast('loading:hide') } }; }])
贴上CacheDataService的代码,写的还不够完善
angular.module('starter.DataCache', []) //数据缓存服务 .factory('CacheDataService',function($http,$q,BaseService,BaseFunction){ var CacheDatas=[]; var CacheTables=["api/BaseInfoGoods/GetGoodsList","api/init/GetInitData","api/BaseArticle/GetList","api/CommonUser/GetUserList_"]; return{ //该方法用于缓存数据 CacheDataFactory:function(InterFaceName,param,Data){ if (BaseFunction.indexofValues(CacheTables,InterFaceName)>-1){ var tmpdata={TableName:InterFaceName,Param:param,Data:Data}; BaseFunction.replaceValueInCache(InterFaceName,param,CacheDatas,tmpdata); return true; }else{ return false; } }, //该方法用于从缓存当中取数据 GetDataFormCache:function(InterFaceName,param){ for (var i=0;i<CacheDatas.length;i++){ if (CacheDatas[i].TableName==InterFaceName&&BaseFunction.CheckParam(CacheDatas[i].Param,param)){ return CacheDatas[i].Data; break; } } return ""; }, //检查是否可缓存 CheckCanCache:function(InterFaceName){ return BaseFunction.indexofValues(CacheTables,InterFaceName)>-1; } } }) .factory('BaseFunction',function($http,$q,BaseService){ return{ //查询某个值在数组当中是否存在,返回ID号,否则返回-1 indexofValues:function(values, value){ for(var i=0;i<values.length;i++) { if (values[i]==value){ return i; break; } } return -1; }, replaceValueInCache:function(InterFaceName,param,CacheDatas,Data){ var b=false; for (var i=0;i<CacheDatas.length;i++){ if (CacheDatas[i].TableName==InterFaceName&&CacheDatas[i].Param==param){ b=true; CacheDatas[i]=Data; break; } } if (!b){ CacheDatas.push(Data); } return CacheDatas; }, CheckParam:function(newvalue,oldvalue){ tmp1=newvalue.substr(0,newvalue.indexOf('&ts=')) tmp2=oldvalue.substr(0,newvalue.indexOf('&ts=')) return tmp2==tmp1; } } });然后在取数据service当中:GetData:function(InterFaceName,param,FromCache){ var mydata=""; if (FromCache) { mydata = CacheDataService.GetDataFormCache('api/' + InterFaceName, param); } if(mydata!=""){//如果该接口可以缓存,而且有缓存数据时直接返回缓存好的数据 var deferred = $q.defer(); deferred.resolve(mydata); return deferred.promise; }else { var baseurl = BaseService.GetServerIP(); var deferred = $q.defer(); var BASE_URL = baseurl + "api/" + InterFaceName + "?" + param; $http({method: 'GET', url: BASE_URL}). success(function (data, status, headers, config) { deferred.resolve(data); }). error(function (data, status, headers, config) { deferred.reject(data); }); return deferred.promise; } },