问题
默认情况下,angular的$http仅仅缓存“get”和’jsonp’的请求数据.
angular $http缓存的源码分析
if ((config
.cache || defaults
.cache)
&& config
.cache !== false &&
(config
.method
=== 'GET' || config
.method
=== 'JSONP')) {
cache = isObject(config
.cache)
? config
.cache
: isObject(defaults
.cache)
? defaults
.cache
: defaultCache;
console
.log(
'cache',
cache);
}
if (
cache) {
cachedResp
= cache.get(url);
...
}
首先我们要通过 config.method和config.cache的校验其次要一个唯一的url,可以利用angular自带的URL编码服务$httpParamSerializer,编码data对象来生成,其他的方法也可以,只要唯一就行另外,如果只是单纯的改成get请求,发给后端的时候,就真是是get请求了。而我们发给后台的应该是post请求。所以第一次请求,必须原封不动的发给后台。这就导致了,我们只能自己创建一个容器来缓存数据。并且是
cacheFactory创建的容器,这样
http才能识别。
方法
将post请求伪装成get请求,让$http可识别缓存POST数据并不难,主要是要让
http读取post的缓存之后,正确的执行后来的success和error方法的回调.所以才需要伪装,才能通过
http的缓存校验,让$http的代码能够执行下去.
$http.post(url,
data).then(success,error);
思路
新建一个拦截器
var myapp=angular.module(
'myapp',[]);
myapp.config(
function ($httpProvider) {
$httpProvider.interceptors.push(
function ($q) {
return {
request:
function (config) {
return config
},
response:
function (response) {
return response;
}
}
})
});
创建一个缓存post数据的容器
var cache=angular.injector([
'ng']).
get(
'$injector').
get(
'$cacheFactory')(
'$httpPost');
在request请求时,判断是否为POST请求,并且设置了cache:true,如果是,并且cache过数据,则伪装为’GET’方法,如果没有cache过则直接pass.
request:function (config) {
if(config
.cache&&config
.method
==='POST'){
var url
=config
.url
+'?'+config
.paramSerializer(config
.data);
console
.log(
'url',url,
cache.get(url));
if(
cache.get(url)){
config
.cache=cache;
config
.method
='GET';
config
.url
=url;
}
}
return config
},
在response返回时,判断是否为POST请求,并且设置了cache:true,如果是则cache它
response:function (response) {
var config
=response
.config;
if(response
.config
.cache&&response
.config
.method
==='POST'){
var url
=config
.url
+'?'+config
.paramSerializer(config
.data);
cache.put(url,response
.data);
console
.log(
'save Cache',url,
cache.get(url));
}
return response;
}
代码
完整demo(angular version 1.5.8)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title
</title>
</head>
<body>
<script src="./angular.js"></script>
<div ng-app="myapp">
<div ng-controller="myctrl">
<span ng-bind="name"></span>
<span ng-bind="age"></span>
<button ng-click="load()">加载
</button>
</div>
</div>
<script>
var myapp=angular.module('myapp',[]);
myapp.config(function ($httpProvider) {
$httpProvider.interceptors.push(function ($q) {
var cache=angular.injector(['ng']).get('$injector').get('$cacheFactory')('$httpPost');
console.info('cache',cache);
return {
request:function (config) {
if(config.cache&&config.method==='POST'){
var url=config.url+'?'+config.paramSerializer(config.data);
console.log('url',url,cache.get(url));
if(cache.get(url)){
config.cache=cache;
config.method='GET';
config.url=url;
}
}
return config
},
requestError:function (rejection) {
console.log('rejection',rejection);
return rejection;
},
response:function (response) {
var config=response.config;
if(response.config.cache&&response.config.method==='POST'){
var url=config.url+'?'+config.paramSerializer(config.data);
cache.put(url,response.data);
console.log('save Cache',url,cache.get(url));
}
return response;
}
}
})
});
myapp.controller('myctrl',function ($scope,$http) {
$scope.name='demo';
$scope.age=100;
$scope.load=function () {
$http({
url:'data.json',
method:'post',
data:{name:1},
cache:true}).success(function (data) {
console.log('ajax result',data);
$scope.name=data.name;
$scope.age=data.age;
}).error(function (error) {
console.error('error',error);
});
};
$scope.load();
})
</script>
</body>
</html>
data.json
{
"
name":
"gyanxie",
"
age":
"万岁万万岁"
}
转载请注明原文地址: https://ju.6miu.com/read-668983.html