限制来自工厂服务的http调用

时间:2017-01-11 10:31:55

标签: angularjs angular-services angular-factory

我使用factory服务使用$http服务获取某些数据。这里的问题,我不想每次都发出http请求,我想在某处保存这些数据,并在需要时获取它的本地副本。为此,我想在factory内创建一个数组,并在第一次调用时将加载的数据分配给它,然后在需要时返回它,而不是从服务器再次加载它。就我而言,每次都会触发http服务。我怎样才能解决这个问题?我看过here,但这不回答我的问题。

这是我的factory

angular.module("app").factory("getDataService", ['$http', function ($http) {
    var usersArray = [];
    if (usersArray.length === 0) {
        return {
            getJsonData: function () {
                return $http.get('https://api.myjson.com/bins/eznv3')
                    .success(function (data, status, headers, config) {
                        usersArray = data;
                        return data;
                    })
                    .error(function (error, status, headers, config) {
                    });
            }
        }
    }else{
        return usersArray;
    }
}]);

这是使用此服务的controller

angular.module("app").controller("ctrl", ["$scope", "getDataService", function ($scope, getDataService) {

    angular.element(document).ready(function () {
            getDataService.getJsonData().then(function (data) {
                $scope.users = data.data;
            });
    });
}]);

3 个答案:

答案 0 :(得分:2)

您可以使用本地存储,这是最好和最简单的方法之一。

LocalStorage.setItem('usersArray',data); 设置本地存储空间中的数据。

LocalStorage.getItem('usersArray'); 从本地存储中检索数据。

这是您工厂的变更,

angular.module("app").factory("getDataService", ['$http', function ($http) {
    var usersArray = LocalStorage.getItem('usersArray');
    if (usersArray.length === 0) {
        return {
            getJsonData: function () {
                return $http.get('https://api.myjson.com/bins/eznv3', {cache: true})
                    .success(function (data, status, headers, config) {
                        usersArray = data;
                        LocalStorage.setItem('usersArray',data);
                        return data;
                    })
                    .error(function (error, status, headers, config) {
                    });
            }
        }
    }else{
        return LocalStorage.getItem('usersArray');
    }
}]);

你的控制器,

angular.module("app").controller("ctrl", ["$scope", "getDataService", function ($scope, getDataService) {

    var x = [];

    angular.element(document).ready(function () {
        if (x.length == 0) {
            getDataService.getJsonData().then(function (data) {
                x = data.data;
                $scope.users = x;
            });
        }else{
            console.log("local copy of data exists");
        }
    });
}]);

localstorage的优势:

  • 使用本地存储,Web应用程序可以在用户的​​浏览器中本地存储数据。
  • 与Cookie不同,存储限制要大得多(至少5MB),信息永远不会传输到服务器。

答案 1 :(得分:1)

您不需要手动缓存$http.get的响应,angularJS本身提供了一种缓存响应的方法。在您工厂的getJsonData函数中尝试以下代码:

getJsonData: function () {
    return $http.get('https://api.myjson.com/bins/eznv3', {cache: true})
    .success(function (data, status, headers, config) {
          return data;
     })
     .error(function (error, status, headers, config) {
     });
}

来源:https://docs.angularjs.org/api/ng/service/$http#get

阅读上述文件。你会从那里找到配置。

答案 2 :(得分:1)

几天前,我有同样的要求,以下是我为此创建的模块代码......

'use strict';
(function() {
    angular.module('httpService', []).service("api", ["$http", "dbService", function($http, dbService) {
        /**
         * <Pankaj Badukale>
         * ()
         * request.url      => Url to request 
         * request.method   => request method
         * request.data     => request data
         * request.mask     => This is custom object for out use
         *
         * @return ()
         */
        return function (request) {
            var url         = (request != undefined && request.url != undefined) ? request.url : "./";
            var method      = (request != undefined && request.method != undefined) ? request.method : "GET";
            var rData       = (request != undefined && request.data != undefined) ? request.data : {};
            /**
             * mask is CUSTOME object we add to request object
             * Which is useful for keep track of each request as well interceptor execute
             * 
             * IT HAS
             *  {
             *      save        : true, //tell that save request response in session
             *      fetch       : true, //check local data first,
             *      fetchSource : tell about perticular source of data DEFAULT WILL BE sessionStorage
             *                    OPTIONS are session and local
             *  } strucutre FOR NOW may be it will better or enhance in future
             *
             * message property to set message in alert
             * doExecute tell wheather you want to execute maskMan code for this request
             *
             * while saving and fetching data from local it uses URL of request as key
             * maskMan is a factory which iterate your error response object and we can add different behaviours for maskMan
             */
            var mask        = {};

            if(request != undefined && request.mask != undefined) {
                mask = request.mask;
            }

            return dbService.http(request).then(function(data) {
                console.log("Data fetched from local "+ request.url);
                return data;
            }, function(err) {
                return $http({
                    url: url,
                    method: method,
                    data: rData,
                    mask: mask,
                    header:{
                            'content-type':'application/json'
                    }
                }).then(function(response) {
                    return response.data;
                },function(error) {
                    return error;
                });
            });
        };
    }]).service('customHttpInterceptor', ["$q", "maskMan", function($q, maskMan) {
        return {
            //before send request to server
            request: function(config) {                 
                    return config;
            },
            //if any found in request object
            requestError: function(rejection) {
                    return $q.reject(rejection);
            },
            //on response come to web app
            response: function(response) {              
                maskMan.responseIterator(response);
                //you to return any thing as response from here
                return response;
            },
            //if there is error in response`
            responseError: function(rejection) {                
                maskMan.statusIterator(rejection);              
                return $q.reject(rejection);
            }
        };
    }]).factory("maskMan", ["dbService", function(dbService) {
        return {
            /**
             * statusIterator
             * Iterate response object on error comes
             */
            statusIterator: function(rejection) {
                if( rejection.config.mask.doExecute == true) {
                    switch(rejection.status) {
                        case 404: this.notFound(rejection);
                            break;
                        default: this.dontKnow(rejection);
                    }   
                }
            },
            /**
             * notFound
             * Function to defined logic for 404 error code scenario's
             * Here we can defined generic as well specific request object conditions also
             */
            notFound: function(rejection) {
                var errMsg = rejection.config.mask.message || "Something wrong";

                alert(errMsg);

                rejection.stopExecute = true;//stop further execute of code flag
            },
            /**
             * dontKnow
             * For every error response this method goingt to envoke by default
             */
            dontKnow: function(maskObject) {
                console.log("Don't know what to do for "+maskObject.config.url);
            },
            /**
             * responseIterator
             * Define logic to do after response come to browser
             * 
             * @params JSON resp
             */
            responseIterator: function(resp) {
                //Logic to save data of response in session storage with mask command save
                if( resp.config.mask !== undefined && resp.config.mask.save === true ) {
                    var sdata   = JSON.stringify(resp.data);
                    var skey    = resp.config.url;

                    dbService.sinsert(skey, sdata);
                }//END
            }
        };
    }]).service("dbService", ["$q", function($q) {
        /**
         * http
         * Custom mirror promise to handle local storage options with http
         * 
         * @params JSON request
         */
        this.http = function(request) {
            var self = this;
            return $q(function(resolve, reject) {
                if( request.mask != undefined && request.mask.fetch === true ) {
                    var data = null;

                    if( request.mask.fetchSource == undefined || request.mask.fetchSource == "session") {//go for default sessionStorage
                        data = JSON.parse(self.sget(request.url));
                    } else if( request.mask.fetchSource == "local" ) {
                        data = JSON.parse(self.get(request.url));
                    } else {
                        reject( "Fetch source is not defined." );
                    }

                    if( data != undefined && data != null ) {
                        resolve(data);
                    } else {
                        reject("Data not saved in local "+request.url);
                    }
                } else {
                    reject("Data not saved in local "+request.url);
                }
            });
        }

        /** 
          * Add/Override data to local storage
          *
          * @params String key
          * @params Array/Json data
          * @params Function callback
          * 
          * @return Boolean/Function
          */
        this.insert =  function(key, data, callback) {          
            localStorage.setItem(key, data);

            if( callback != undefined ) {
                callback();
            } else {
                return true;
            }
        }

         /** 
           * Update data of local storage
           * This function generally used to data which is already exist and need to update
           * 
           * @params String key
           * @params Array/Json data
           * @params Function callback
           * 
           * @return Boolean/Function
           */
        this.update = function(key, data, callback) {
            var self = this;
            self.view(key, function(localData) {//callback function
                if( localData != undefined && localData != null ) {
                    //already some data exist on this key So need to update it
                    data = localData.push(data);
                }
                //just handover to insert
                if( callback !== undefined ) {
                    self.insert(key, data, callback);
                } else {
                    return self.insert(key, data);
                }
            });         
        }

         /**
           * Remove data from local storage on basis of key
           * 
           * @params String key
           * @return Boolean
           */
        this.remove = function(key, callback) {
                localStorage.removeItem(key);

                if( callback !== undefined ) {
                    callback();
                } else {
                    return true;
                }
        }

        /**
          * Get key data of local storage
          * @param String key
          * 
          * @return Array data WHEN all data    OR
          * @return String data WHEN key value
          */
        this.get = function(key, callback) {
            var key = key || "";
            var data = [];

            if( key == "" ) {
                //get all data
                for(var i in localStorage) {
                    data.push(JSON.parse(localStorage[i]));
                }
            } else {
                //get one key data
                data = localStorage.getItem(key);
            }

            if(callback != undefined) {
                callback(data);
            } else {
                return data;
            }
        }

        /** 
          * sinsert
          * Add/Override data to session storage
          *
          * @params String key
          * @params Array/Json data
          * @params Function callback
          * 
          * @return Boolean/Function
          */
        this.sinsert =  function(key, data, callback) {
            var key = this.encode(key);

            sessionStorage.setItem(key, data);

            if( callback != undefined ) {
                callback();
            } else {
                return true;
            }
        }

         /** 
           * supdate
           * Update data of session storage
           * This function generally used to data which is already exist and need to update
           * 
           * @params String key
           * @params Array/Json data
           * @params Function callback
           * 
           * @return Boolean/Function
           */
        this.supdate = function(key, data, callback) {
            var self = this;
            self.view(key, function(localData) {//callback function
                if( localData != undefined && localData != null ) {
                    //already some data exist on this key So need to update it
                    data = localData.push(data);
                }
                //just handover to insert
                if( callback !== undefined ) {
                    self.insert(key, data, callback);
                } else {
                    return self.insert(key, data);
                }
            });         
        }

         /**
           * sremove
           * Remove data from session storage on basis of key
           * 
           * @params String key
           * @return Boolean
           */
        this.sremove = function(key, callback) {
                var key = this.encode(key);

                sessionStorage.removeItem(key);

                if( callback !== undefined ) {
                    callback();
                } else {
                    return true;
                }
        }

        /**
          * get
          * Get key data of session storage
          * @param String key
          * 
          * @return Array data WHEN all data    OR
          * @return String data WHEN key value
          */
        this.sget = function(key, callback) {
            var key = key || "";
            var data = [];

            if( key == "" ) {
                //get all data
                for(var i in sessionStorage) {
                    data.push(JSON.parse(sessionStorage[i]));
                }
            } else {
                //get one key data
                key = this.encode(key);

                data = sessionStorage.getItem(key);
            }

            if(callback != undefined) {
                callback(data);
            } else {
                return data;
            }
        }

        /**
          * encode
          * encode give string using javascript
          *
          * @param String str
          * @return String
          */        
        this.encode = function(str) {
            return btoa(str);
        }

        /**
          * decode
          * decode give string using javascript
          *
          * @param String str
          * @return String
          */                
        this.decode = function(str) {
            return atob(str);
        }

        return this;

    }]).config(['$httpProvider', function($httpProvider) {
            $httpProvider.interceptors.push('customHttpInterceptor');
    }]);
})();

如何使用它::

在您的项目中包含此模块....

然后使用“httpService”始终用于http请求所有API调用...

我们需要将配置对象传递给此服务告诉API调用以及应该如何处理....您可以在代码本身中找到有关配置的详细信息......

那么如何在控制器中使用..

module.controller('nameofController', ['httpService', function(httpService)  {
    httpService({
        url: 'Your API url',
        method: 'GET',
        mask: {
                  save        : true, //tell that save request response in session
                  fetch       : true, //check local data first before next fetch,
                  fetchSource : tell about perticular source of data DEFAULT WILL BE sessionStorage OPTIONS are session and local
             }
    }).then(function(data) {
        // promise is all same as $http
        console.log(data);
    });
}]);

希望这会有所帮助......您可以使用非常简单的解决方案来标记

  

{cache: true}

... 但是这个解决方案是完全自定义的,并且在所有控制下

生产中使用的原始代码位于gist