限制来自工厂服务的 http 调用
Limit http calls from a factory service
我正在使用 factory
服务通过 $http
服务获取一些数据。这里的问题是,我不想每次都发出 http
请求,我想将这些数据保存在某个地方并在需要时获取它的本地副本。为此,我想在 factory
内部创建一个数组,并在第一次调用时将加载的数据分配给它,然后在需要时只 return 它,而不是从服务器再次加载它。在我的例子中,http
服务每次都会被触发。我怎样才能解决这个问题?我阅读了 ,但这并没有回答我的问题。
这是我的 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;
});
});
}]);
您不需要手动缓存$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
阅读以上文件。您将从那里找到配置。
您可以使用 Local Storage,这是最好和最简单的方法之一。
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)并且信息永远不会传输到服务器。
几天前,我得到了同样的要求,下面是我为同样的要求创建的模块代码...
'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');
}]);
})();
如何使用它::
在您的项目中包含此模块....
然后始终对 http 请求使用 "httpService" 所有 API 调用...
我们需要将配置对象传递给此服务,告知有关 API 调用以及应该如何处理....您可以在代码本身中找到有关配置的详细信息...
那么如何在controller中使用..
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
我正在使用 factory
服务通过 $http
服务获取一些数据。这里的问题是,我不想每次都发出 http
请求,我想将这些数据保存在某个地方并在需要时获取它的本地副本。为此,我想在 factory
内部创建一个数组,并在第一次调用时将加载的数据分配给它,然后在需要时只 return 它,而不是从服务器再次加载它。在我的例子中,http
服务每次都会被触发。我怎样才能解决这个问题?我阅读了
这是我的 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;
});
});
}]);
您不需要手动缓存$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
阅读以上文件。您将从那里找到配置。
您可以使用 Local Storage,这是最好和最简单的方法之一。
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)并且信息永远不会传输到服务器。
几天前,我得到了同样的要求,下面是我为同样的要求创建的模块代码...
'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');
}]);
})();
如何使用它::
在您的项目中包含此模块....
然后始终对 http 请求使用 "httpService" 所有 API 调用...
我们需要将配置对象传递给此服务,告知有关 API 调用以及应该如何处理....您可以在代码本身中找到有关配置的详细信息...
那么如何在controller中使用..
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