1.0.12 • Published 6 years ago

ng-request-cache v1.0.12

Weekly downloads
3
License
ISC
Repository
github
Last release
6 years ago

ng-request-cache

AngularJS HTTP request cache for IndexeDB and $cacheFactory

angularJS 下的restFul数据请求缓存服务及服务器端缓存服务, 实现服务器-客户端的数据请求三级缓存服务架构.

  • 服务器端采用MemcacheRedis作为缓存服务器, 缓存数据库中的数据, 提供给客户端只读操作查询;
  • 客户端第一级本地缓存采用angularJs$cacheFactory服务, 数据存放在内存中, 当第一次启动项目或$cacheFactory中没有指定数据时查询二级缓存
  • 客户端第二级本地缓存采用IndexedDB数据库, 进行永久数据缓存
  • 客户端对服务器数据库的写操作使用requestCacheFactory.request()方法, 服务器端处理完客户端的写操作请求后自动删除对应的服务器缓存,以待下一次客户端读操作请求时重建
  • 客户端对服务器数据库的读操作使用requestCacheFactory.readonly()方法
    • 如果读操作请求操作前端已做缓存, 同时请求时间在最后缓存时间的configs.cache_timeout设置时间内, 则本次请求不向服务器发出请求, 返回的结果是前端已做的缓存.
    • 如果读操作请求操作前端已做缓存, 但请求时间在最后缓存时间的configs.cache_timeout设置时间外, 则本次请求将向服务器发出缓存校验参数, 服务器验证校验参数一致, 服务器不做数据返回, 数据仍从前端缓存中获取, 以减少服务器的带宽压力和前端的流量压力; 如果服务器验证校验参数不一致, 则从服务器向前端返回最终数据.
    • 如果读操作请求操作前端未做缓存, 则从服务器向前端返回最终数据.

解决的问题

AngularJs Routercache不能按需缓存和请求数据!

  1. AngularJs Routercache打开的情况下, 只有第一次访问该路由, 才向服务器发出数据请求, 后续对该路由的访问都是得到客户端已缓存的数据
  2. AngularJs Routercache关闭的情况下, 每次访问该路由都向服务器发出数据请求

ng-unit unitFactory for web PC 工具类自定义服务

  • 需要在index.html入口页面引入的CSS文件
    <link href="https://cdn.bootcss.com/toastr.js/latest/css/toastr.min.css" rel="stylesheet">
    <link href="https://cdn.bootcss.com/sweetalert/1.1.3/sweetalert.css" rel="stylesheet">
  • 需要在index.html入口页面引入的JS文件
    <script type="text/javascript" src="https://cdn.bootcss.com/underscore.js/1.8.3/underscore-min.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/spin.js/2.3.2/spin.min.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/toastr.js/latest/js/toastr.min.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/sweetalert/1.1.3/sweetalert.min.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/angular.js/1.6.9/angular.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/angular-filter/0.5.17/angular-filter.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/oclazyload/1.1.0/ocLazyLoad.min.js"></script>
    <script type="text/javascript" src="node_modules/angular-indexedDB/angular-indexed-db.min.js"></script>
    <script type="text/javascript" src="node_modules/ng-request-cache/ng-unit-webpc.js"></script>
    <script type="text/javascript" src="node_modules/ng-request-cache/ng-request-cache.js"></script>
  • 加载到你的模块, 并进行的配置.
    var app = angular.module('myApp', ['oc.lazyLoad', 'angular.filter', 'xc.indexedDB', 'ng-unit', 'ng-request-cache']);
    app.constant('app_config', {
       db_name: 'myIndexedDB',
       swal: {
           allowOutsideClick: false,		// 如果设置为“true”,用户可以通过点击警告框以外的区域关闭警告框。
    			confirmButtonColor: "#DD6B55",	// 该参数用来改变确认按钮的背景颜色(必须是一个HEX值)。
    			confirmButtonText: "确定",		// 该参数用来改变确认按钮上的文字。如果设置为"true",那么确认按钮将自动将"Confirm"替换为"OK"。
    			type: 'info',					// 窗口的类型。有4种类型的图标动画:"warning", "error", "success" 和 "info".可以将它放在"type"数组或通过第三个参数传递。
    			title: null,					// 窗口的名称。可以通过对象的"title"属性或第一个参数进行传递。
    			text: null,						// 窗口的描述。可以通过对象的"text"属性或第二个参数进行传递。
    			showCancelButton: false,		// 如果设置为“true”,“cancel”按钮将显示,点击可以关闭警告框。
    			showConfirmButton: true,		// 如果设置为“false”,“Confirm”按钮将不显示。
    			cancelButtonText: '取消',		// 该参数用来改变取消按钮的文字。
    			closeOnConfirm: true,			// 如果希望以后点击了确认按钮后模态窗口仍然保留就设置为"false"。该参数在其他SweetAlert触发确认按钮事件时十分有用。
    			timer: null						// 警告框自动关闭的时间。单位是ms。
       },
       spin: {
           type: 'spinner',
           opts: {
               lines: 13,                  // The number of lines to draw
    				length: 38,                 // The length of each line
    				width: 22,                  // The line thickness
    				radius: 49,                 // The radius of the inner circle
    				scale: 1,                   // Scales overall size of the spinner
    				corners: 1,                 // Corner roundness (0..1)
    				color: '#333333',           // CSS color or array of colors
    				fadeColor: 'transparent',   // CSS color or array of colors
    				opacity: 0.3,               // Opacity of the lines
    				rotate: 0,                  // The rotation offset
    				direction: 1,               // 1: clockwise, -1: counterclockwise
    				speed: 1,                   // Rounds per second
    				trail: 60,                  // Afterglow percentage
    				fps: 20,                    // Frames per second when using setTimeout() as a fallback in IE 9
    				zIndex: 2e9,                // The z-index (defaults to 2000000000)
    				className: 'spinner',       // The CSS class to assign to the spinner
    				top: '50%',                 // Top position relative to parent
    				left: '50%',                // Left position relative to parent
    				shadow: 'none',             // Box-shadow for the lines
    				position: 'absolute'        // Element positioning
           }
       },
       sendSmsWait: 60,
       extended_timeout: 2000,
       duration_timeout: 10000,
       hint_type: 'toastr',
       restful: {
           url: 'http://www.yoursite.com/app.php?s=/Api/angular.html',
    			cache: false,
    			timeout: 1000 * 15,
       },
       cache_timeout: 5*60*1000,
    });

ng-unit unitFactory for Ionic & Cordova 工具类自定义服务

  • 需要在index.html入口页面引入的CSS文件
    <link href="https://cdn.bootcss.com/ionic/1.3.2/css/ionic.css" rel="stylesheet">
    <link href="https://cdn.bootcss.com/toastr.js/latest/css/toastr.min.css" rel="stylesheet">
    <link href="https://cdn.bootcss.com/sweetalert/1.1.3/sweetalert.css" rel="stylesheet">
  • 需要在index.html入口页面引入的JS文件
    <script type="text/javascript" src="https://cdn.bootcss.com/underscore.js/1.8.3/underscore-min.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/spin.js/2.3.2/spin.min.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/toastr.js/latest/js/toastr.min.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/sweetalert/1.1.3/sweetalert.min.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/angular.js/1.6.9/angular.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/ionic/1.3.2/js/ionic.bundle.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/ng-cordova/0.1.27-alpha/ng-cordova.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/angular-filter/0.5.17/angular-filter.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/oclazyload/1.1.0/ocLazyLoad.min.js"></script>
    <script type="text/javascript" src="node_modules/angular-indexedDB/angular-indexed-db.min.js"></script>
    <script type="text/javascript" src="node_modules/ng-request-cache/ng-unit-cordova.js"></script>
    <script type="text/javascript" src="node_modules/ng-request-cache/ng-request-cache.js"></script>
    <script type="text/javascript" src="cordova.js"></script>
  • 需要安装的 cordova 插件
    cordova plugin add cordova-plugin-x-toast
    cordova plugin add cordova-plugin-http
  • 加载到你的模块, 并进行的配置.
    var app = angular.module('myApp', ['ionic', 'ngCordova', 'oc.lazyLoad', 'angular.filter', 'xc.indexedDB', 'ng-unit', 'ng-request-cache']);
    app.constant('app_config', {
       db_name: 'myIndexedDB',
       swal: {
           allowOutsideClick: false,		// 如果设置为“true”,用户可以通过点击警告框以外的区域关闭警告框。
    			confirmButtonColor: "#DD6B55",	// 该参数用来改变确认按钮的背景颜色(必须是一个HEX值)。
    			confirmButtonText: "确定",		// 该参数用来改变确认按钮上的文字。如果设置为"true",那么确认按钮将自动将"Confirm"替换为"OK"。
    			type: 'info',					// 窗口的类型。有4种类型的图标动画:"warning", "error", "success" 和 "info".可以将它放在"type"数组或通过第三个参数传递。
    			title: null,					// 窗口的名称。可以通过对象的"title"属性或第一个参数进行传递。
    			text: null,						// 窗口的描述。可以通过对象的"text"属性或第二个参数进行传递。
    			showCancelButton: false,		// 如果设置为“true”,“cancel”按钮将显示,点击可以关闭警告框。
    			showConfirmButton: true,		// 如果设置为“false”,“Confirm”按钮将不显示。
    			cancelButtonText: '取消',		// 该参数用来改变取消按钮的文字。
    			closeOnConfirm: true,			// 如果希望以后点击了确认按钮后模态窗口仍然保留就设置为"false"。该参数在其他SweetAlert触发确认按钮事件时十分有用。
    			timer: null						// 警告框自动关闭的时间。单位是ms。
       },
       spin: {
           type: 'spinner',
           opts: {
               lines: 13,                  // The number of lines to draw
    				length: 38,                 // The length of each line
    				width: 22,                  // The line thickness
    				radius: 49,                 // The radius of the inner circle
    				scale: 1,                   // Scales overall size of the spinner
    				corners: 1,                 // Corner roundness (0..1)
    				color: '#333333',           // CSS color or array of colors
    				fadeColor: 'transparent',   // CSS color or array of colors
    				opacity: 0.3,               // Opacity of the lines
    				rotate: 0,                  // The rotation offset
    				direction: 1,               // 1: clockwise, -1: counterclockwise
    				speed: 1,                   // Rounds per second
    				trail: 60,                  // Afterglow percentage
    				fps: 20,                    // Frames per second when using setTimeout() as a fallback in IE 9
    				zIndex: 2e9,                // The z-index (defaults to 2000000000)
    				className: 'spinner',       // The CSS class to assign to the spinner
    				top: '50%',                 // Top position relative to parent
    				left: '50%',                // Left position relative to parent
    				shadow: 'none',             // Box-shadow for the lines
    				position: 'absolute'        // Element positioning
           }
       },
       sendSmsWait: 60,
       extended_timeout: 2000,
       duration_timeout: 10000,
       hint_type: 'toastr',
       restful: {
           url: 'http://www.yoursite.com/app.php?s=/Api/angular.html',
    			cache: false,
    			timeout: 1000 * 15,
       },
       cache_timeout: 5*60*1000,
    });

依赖/加载与配置

  1. PC WEB 项目和 Cordova APP 项目都必须引入的文件

    • 下载本服务所使用的$indexedDB本地数据库服务封装, 并且在你的index.html中加载它.

        # CMD 安装
        bower install --save angular-indexed-db
        
        # HTML 引入
        <script src="path/to/angular-indexedDB/src/indexeddb.js"></script> 
        
    • 下载本服务所使用的SweetAlert弹框服务封装, 并且在你的index.html中加载它.

        # CMD 安装
        npm install sweetalert
        
        # HTML 引入
        <script src="dist/sweetalert.min.js"></script>
        <link rel="stylesheet" type="text/css" href="dist/sweetalert.css">
  2. 针对不同的平台引入相应的Toast消息提醒模块

    • PC WEB 项目安装并引入

        # CMD 安装
        npm install --save angularjs-toaster
        
        # HTML 引入
        <link href="path/to/angularjs-toaster/1.1.0/toaster.min.css" rel="stylesheet" />
        <script src="path/to/angularjs/angular.min.js" ></script>
        <script src="path/to/angular-animate.min.js" ></script>
        <script src="path/to/angularjs-toaster/toaster.min.js"></script>
    • Cordova APP 项目安装 $cordovaToast 插件

        # CMD 安装
        cordova plugin add https://github.com/EddyVerbruggen/Toast-PhoneGap-Plugin.git
  3. 安装(使用GIT克隆 或者 使用NPM安装)

    • 使用GIT克隆
    git clone https://github.com/GadflyBSD/ng-request-cache.git
    • 使用NPM安装
    npm install ng-request-cache
  4. 在你的index.html 加载它.

    <script src="path/to/request-cache-indexeddb.js"></script>          // PC WEB 项目引入
    <script src="path/to/request-cache-indexeddb-cordova.js"></script>  // Cordova APP 项目引入
  5. 加载到你的模块, 并进行配置.

    var app = angular.module('myApp', ['xc.indexedDB', 'request-cache-indexeddb']);
    app.constant('configs', {
        db_name: 'myIndexedDB',
        restful_url: 'http://www.yoursite.com/app.php?s=',
        http_timeout: 15,
        cache_timeout: 5*60,
    });
    app.run(function($window, configs){
        var initialize_APP = $window.localStorage.getItem('initialize_APP');
        if (!initialize_APP || angular.isUndefined(initialize_APP) || initialize_APP === null ){
            $indexedDBProvider.connection(configs.db_name)
                .upgradeDatabase(1.0.0, function(event, db, tx){
                    var memcacheStore = db.createObjectStore('memcache', {keyPath: 'key', autoIncrement: true});
                    memcacheStore.createIndex('md5', 'md5', {unique: false});
                    memcacheStore.createIndex('sha1', 'sha1', {unique: false});
                    var documentStore = db.createObjectStore('document', {keyPath: 'id'});
                    documentStore.createIndex('did', 'did', {unique: false});
                    documentStore.createIndex('title', 'title', {unique: false});
                    documentStore.createIndex('category_id', 'category_id', {unique: false});
                    documentStore.createIndex('category_name', 'category_name', {unique: false});
                    documentStore.createIndex('category_title', 'category_title', {unique: false});
                    documentStore.createIndex('url', 'url', {unique: false});
                    documentStore.createIndex('level', 'level', {unique: false});
                    documentStore.createIndex('status', 'status', {unique: false});
                });
            $window.localStorage.setItem('initialize_APP', true);
        }
    });
    app.config(function($stateProvider, $urlRouterProvider, $httpProvider, $indexedDBProvider) {
        $httpProvider.defaults.headers = {
            post: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'cache':false
            },
            get: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            put: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            delete: {
                'Content-Type': 'application/x-www-form-urlencoded'
            }
        }
        $httpProvider.defaults.cache = false;
        $httpProvider.defaults.transformRequest = function(obj) {
            var str = [];
            for (var p in obj) {
                str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
            }
            return str.join("&");
        };
        $stateProvider.state('app.mTenderTasks',{
            url:'/mTenderTasks',
            cache:false,            // 请取消路由中的缓存
            views:{
                 'tab-my':{
                    templateUrl:'templates/tab-my/mTenderTasks.html',
                    controller: 'myTenderTasksCtrl'
                 }
            }
        });
    });

基本用法

一. 前端数据请求
  • 常规请求模式

    app.controller('yourCtrl', function($scope, requestCacheFactory){
        /**
         * # 常规数据请求, 根据服务器返回值缓存数据或直接返回数据
         * @param param		Object  请求参数, 服务器端具体方法所接收的请求参数
         * @param router	Object  请求的服务器端路由参数, 
                                    对象成员action代表服务器控制器名, 
                                    对象成员model代表服务器模型名, 
                                    对象成员module代表服务器方法名, 
                                    对象成员key代表请求结果通过$cacheFactory进行缓存的KEY值(不设定则不做缓存), 
                                    默认"{action: 'Restful', module: 'getServiceData'}", 
                                    请求的服务器端路由参数如指定, action或model必须指定一个, 
                                    如果两个都指定, 服务器端调用model模型中的module方法返回数据.
         * @param method	String  请求方法: get(默认), post, put, delete
         */
        requestCacheFactory.request(param, router, method).then(function(success){
            Success Request do someing ...
        }, function(error){
            Error Request do someing ...
        });
    });
  • 请求获取服务器已缓存的指定数据(校验缓存)

    • 如果请求操作前端已做缓存, 同时请求时间在最后缓存时间的configs.cache_timeout设置时间内, 则本次请求不向服务器发出请求, 返回的结果是前端已做的缓存.
    • 如果请求操作前端已做缓存, 但请求时间在最后缓存时间的configs.cache_timeout设置时间外, 则本次请求将向服务器发出缓存校验参数, 服务器验证校验参数一致, 服务器不做数据返回, 数据仍从前端缓存中获取, 以减少服务器的带宽压力和前端的流量压力; 如果服务器验证校验参数不一致, 则从服务器向前端返回最终数据.
    • 如果请求操作前端未做缓存, 则从服务器向前端返回最终数据.
    app.controller('yourCtrl', function($scope, requestCacheFactory){
        /**
         * 请求获取服务器已缓存的指定数据(校验缓存)
         * @param getItem   String|Array    // 向服务器缓存请求数据的KEY值
         * @param merge: {  Object          // 合并请求数据的请求参数, 不设定则不向服务器合并请求数据
         * 			action: String, // 对应服务器控制器名,非必须
         * 			model: String,  // 对应服务器模型名,非必须
         * 			module: String  // 对应服务器方法名,非必须
         * 			key: String     // 请求结果通过$cacheFactory进行缓存的KEY值(不设定则不做缓存), 非必须
         * 			param: Object   // 服务器端具体方法所接收的请求参数, 非必须
         * 		},
         */
        requestCacheFactory.readonly(getItem, merge).then(function(success){
            Success Request do someing ...
        }, function(error){
            Error Request do someing ...
        });
    });
二. 服务器端数据请求的接收与返回

本例中采用Memcache作为服务器缓存服务, 也可以选择使用Redis作为缓存服务使用

  • 服务器接收到前端客户端所传递的数据参数格式:
 {
   "action": "服务器控制器名",
   "model": "服务器模型名",
   "module": "服务器方法名",
   "data": {
     "uid": "用户uid",
     "uuid": "用户UUID",
     ......
   },
   "check": [
     {"key": "需要验证的服务器缓存KEY1", "md5": "md5", "sha1": "sha1"},
     {"key": "需要验证的服务器缓存KEY2", "md5": "md5", "sha1": "sha1"},
     ...
     {"key": "需要验证的服务器缓存KEYn", "md5": "md5", "sha1": "sha1"}
   ],
   "merge": {
     "action": "合并请求服务器控制器名",
     "model": "合并请求服务器模型名",
     "module": "合并请求服务器方法名",
   }
 }
  • 服务器传递给客户端的数据格式:

    1. 所有返回的需要缓存的数据(localStorage, sessionStorage, indexeddb, cache)请使用key-value的对象形式返回({"key": "data"}), 如有多个类型的数据请以key-value的数组对象形式返回([{"key1": "data1"}, {"key1": "data1"}, ... {"keyN": "dataN"}]).
    2. indexeddb.structure是客户端IndexdDB数据库对象的创建结构, 可以不指定, 不指定时将默认创建一个db.createObjectStore('key', {keyPath: 'id', autoIncrement: true})的对象存储空间
    3. 服务器端返回数据的相关JSON格式约定:
     {
       "type": "请求返回状态: Success/Error/Info",
       "msg": "请求返回说明",
       "localStorage": {
         "key1": {    // 此处key值为服务器端数据KEY
           "key": "服务器端数据KEY",
           "md5": "服务器端缓存数据的MD5校验值",
           "sha1": "服务器端缓存数据的SHA1校验值",
           "verify": "服务器对比客户端校验结果, 如果为true则不会有data返回, 说明客户端与服务器数据一致",
           "data": "需要客户端进行localStorage方式缓存的数据, 对象或数据对象"
         },
         "key2": {    // 此处key值为服务器端数据KEY
           "key": "服务器端数据KEY",
           "md5": "服务器端缓存数据的MD5校验值",
           "sha1": "服务器端缓存数据的SHA1校验值",
           "verify": "服务器对比客户端校验结果, 如果为true则不会有data返回, 说明客户端与服务器数据一致",
           "data": "需要客户端进行localStorage方式缓存的数据, 对象或数据对象"
         },
         ......
         "keyN": {    // 此处key值为服务器端数据KEY
           "key": "服务器端数据KEY",
           "md5": "服务器端缓存数据的MD5校验值",
           "sha1": "服务器端缓存数据的SHA1校验值",
           "verify": "服务器对比客户端校验结果, 如果为true则不会有data返回, 说明客户端与服务器数据一致",
           "data": "需要客户端进行localStorage方式缓存的数据, 对象或数据对象"
         }
       },
       "sessionStorage": "需要客户端进行sessionStorage方式缓存的数据, 对象或数据对象, 结构同localStorage",
       "indexeddb": {
        "key1": {    // 此处key值为服务器端数据KEY
          "key": "服务器端数据KEY",
          "md5": "服务器端缓存数据的MD5校验值",
          "sha1": "服务器端缓存数据的SHA1校验值",
          "structure": {
            "storeName": "对象空间名称",
            "keyPath": "指定每条记录中的某个指定字段作为键值",
            "autoIncrement": "是否自动生成的递增数字作为键值, 可以不指定, 如果与keyPath同时使用, 对象中有keyPath指定的属性则不生成新的键值,如果没有自动生成递增键值,填充keyPath指定属性",
            "createIndex": [
              {"name": "索引名称", "idx": "索引字段名", "unique": "是否唯一"}
              ......
            ]
         },
          "verify": "服务器对比客户端校验结果, 如果为true则不会有data返回, 说明客户端与服务器数据一致",
          "data": "需要客户端进行indexedDB方式缓存的数据, 对象或数据对象"
        },
        "key2": {    // 此处key值为服务器端数据KEY
          "key": "服务器端数据KEY",
          "md5": "服务器端缓存数据的MD5校验值",
          "sha1": "服务器端缓存数据的SHA1校验值",
          "structure": {
             "storeName": "对象空间名称",
             "keyPath": "指定每条记录中的某个指定字段作为键值",
             "autoIncrement": "是否自动生成的递增数字作为键值, 可以不指定, 如果与keyPath同时使用, 对象中有keyPath指定的属性则不生成新的键值,如果没有自动生成递增键值,填充keyPath指定属性",
             "createIndex": [
               {"name": "索引名称", "idx": "索引字段名", "unique": "是否唯一"}
               ......
             ]
          },
          "verify": "服务器对比客户端校验结果, 如果为true则不会有data返回, 说明客户端与服务器数据一致",
          "data": "需要客户端进行indexedDB方式缓存的数据, 对象或数据对象"
        },
        ......
        "keyN": {    // 此处key值为服务器端数据KEY
          "key": "服务器端数据KEY",
          "md5": "服务器端缓存数据的MD5校验值",
          "sha1": "服务器端缓存数据的SHA1校验值",
          "structure": {
             "storeName": "对象空间名称",
             "keyPath": "指定每条记录中的某个指定字段作为键值",
             "autoIncrement": "是否自动生成的递增数字作为键值, 可以不指定, 如果与keyPath同时使用, 对象中有keyPath指定的属性则不生成新的键值,如果没有自动生成递增键值,填充keyPath指定属性",
             "createIndex": [
               {"name": "索引名称", "idx": "索引字段名", "unique": "是否唯一"}
               ......
             ]
          },
          "verify": "服务器对比客户端校验结果, 如果为true则不会有data返回, 说明客户端与服务器数据一致",
          "data": "需要客户端进行indexedDB方式缓存的数据, 对象或数据对象"
        }
      },
       "cache": "需要客户端进行$cacheFactory方式缓存的数据, 对象或数据对象, 结构同localStorage",
       "data": "服务器返回的一般数据",
       "merge": "服务器返回合并请求数据"
     }
1.0.12

6 years ago

1.0.11

6 years ago

1.0.10

6 years ago

1.0.9

6 years ago

1.0.8

6 years ago

1.0.7

6 years ago

1.0.6

6 years ago

1.0.5

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago