angular 缓存post请求的方法

这篇博客探讨了在Angular中如何实现POST请求的缓存。默认情况下,$http只缓存GET和jsonp请求。文章通过分析Angular的$http源码,提出了解决方案:通过创建拦截器和自定义缓存容器,将POST请求伪装成GET请求进行缓存。当POST请求带有cache: true时,拦截器会检查是否有缓存数据,若有则使用缓存并保持success和error回调的正确执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

  • 默认情况下,angular的$http仅仅缓存“get”和’jsonp’的请求数据.

angular $http缓存的源码分析

// line 11737

      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请求。所以第一次请求,必须原封不动的发给后台。这就导致了,我们只能自己创建一个容器来缓存数据。并且是cacheFactoryhttp才能识别。

方法

  • 将post请求伪装成get请求,让$http可识别
  • 缓存POST数据并不难,主要是要让httppostsuccesserror.http的缓存校验,让$http的代码能够执行下去.
   $http.post(url,data).then(success,error);
  • 思路

    1. 新建一个拦截器

       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;
                }
            }
        })
      });
      
    2. 创建一个缓存post数据的容器

       var cache=angular.injector(['ng']).get('$injector').get('$cacheFactory')('$httpPost');
    3. 在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
                },
    4. 在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":"万岁万万岁"
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值