angular Cache Method for post Request

problem By default, angular's $http caches only the request data for "get" and "jsonp". Source code analysis of angular $htt...

problem

  • By default, angular's $http caches only the request data for "get" and "jsonp".

Source code analysis of angular $http cache

// line 11737 if ((config.cache || defaults.cache) && config.cache !== false && (config.method === 'GET' || config.method === 'JSONP')) {//Determine whether to cache cache = isObject(config.cache) ? config.cache : isObject(defaults.cache) ? defaults.cache : defaultCache; console.log('cache',cache);//Selecting Cache Objects } if (cache) { cachedResp = cache.get(url);//Getting Cache ... }
  • First we need to pass the config.method and config.cache checks.
  • Next, you need a unique url, which can be generated by encoding data objects using angular's own URL encoding service, $http ParamSerializer, or other methods, as long as it's unique.
  • In addition, if you simply change the get request and send it to the back end, it's really a get request. And we should send back-end post requests. Therefore, the first request must be sent to the backstage in its original form. This leads to the fact that we can only create a container to cache the data ourselves. And it's a container created by cacheFactory so that http can recognize it.

Method

  • Disguise the post request as a get request to make $http recognizable
  • Caching POST data is not difficult, mainly to enable HTTP to read post's cache and correctly execute subsequent callbacks of success and error methods. Therefore, camouflage is needed to pass http's cache validation so that the $http code can be executed.
$http.post(url,data).then(success,error);
  • thinking

    1. New Interceptor

      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. Create a container for caching post data

      var cache=angular.injector(['ng']).get('$injector').get('$cacheFactory')('$httpPost');
    3. When requesting a request, determine whether it is a POST request and set cache:true. If it is, and the cache has passed the data, it masquerades as the'GET'method and passes directly if there is no cache.

      request:function (config) { if(config.cache&&config.method==='POST'){ //Start counting 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. When response returns, determine whether it is a POST request, and set cache:true, if so, cache it

      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; }

Code

  • Complete 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()">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'){ //Start counting 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:, 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":"Long live long live long live long live" }

9 July 2019, 16:19 | Views: 9937

Add new comment

For adding a comment, please log in
or create account

0 comments