Reputation: 15291
I have created a service that provides my AngularJS app with data, it's rather simple the service just contains lots a method that make a $http
call. The problem is that this call is made everytime when a HTML item in my view (a div of product details) is visible in the view port (I'm lazy loading), thus it is possible for the user to scroll straight to the bottom of the page, etc and create a number of requests (usually around 50 - 60) that will block/slow down other requests or the app on the whole. Thus I need a way to limit, restrict, queue or delay the requests - queuing would be best, but for the time being I was just going to restrict / manage the amount of requests in the service.
This is how I call my service in my controllers / directives:
productAvailabilityService.getAvailability(scope.productId).then(function (result) {
// do stuff with the result...
});
and this is the service
.factory('productAvailabilityService', function ($http) {
var prodAv = {};
prodAv.getAvailability = function (productId) {
return $http({
method: 'GET',
url: '/api/product/getAvailability',
params: {
'productId': productId
}
}).then(
function (response) {
return response;
}, function () {
return 0;
});
}
};
return prodAv;
});
Now I want to add the limiting functionality... like so:
.factory('productAvailabilityService', function ($http) {
var prodAv = {};
prodAv.requests = 0;
prodAv.getAvailability = function (productId) {
if (prodAv.requests > 6) {
return function () {
return 'Too many requests';
};
} else {
prodAv.requests++;
return $http({
method: 'GET',
url: '/api/product/:productId/getAvailability',
params: {
'productId': productId
}
}).then(
function (response) {
prodAv.requests--;
return response;
}, function () {
prodAv.requests--;
return 0;
});
}
};
return prodAv;
});
This gives me an error when the number of requests is greater than 6, .getAvailability(...).then is not a function
which I don't seem to be able to fix, can anyone see what I am doing wrong... also this method does seem a little wrong, is there a better way to manage the amount of times I can call a service / run a $http
request? Thanks in advance!
Upvotes: 2
Views: 3030
Reputation: 31
Add this DelayHttp
app.factory('DelayHttp', ($http, $timeout) => {
let counter = 0,
delay = 100;
return (conf) => {
counter += 1;
return $timeout(() => {
counter -= 1;
return $http(conf);
}, counter * delay);
};
});
Usage:
return DelayHttp({
url: url,
method: 'GET',
params: params
});
Which queues and executes the requests by 100ms apart or max 10 requests/second. You can adjust the delay to match your desired throughput.
Upvotes: 1
Reputation: 4067
You have to use a promise for productAvailabilityService. You return a function instead of a promise, so the "then()" throw an error in the first line code..
here is the fraction of code with the promise:
.factory('productAvailabilityService', function ($http,$q) {
var prodAv = {};
prodAv.requests = 0;
prodAv.getAvailability = function (productId) {
if (prodAv.requests > 6) {
var deferred = $q.defer();
deferred.reject("no more than 6 calls");
return deferred.promise;
}else{ //etc.
you could maybe also use the resolve function if you manage a delayed call,
Upvotes: 1
Reputation: 5435
i would set a time gap and wait until the user arrived its desired content before issuing the requests something like
var timer;
function getData(){
$timeout.cancel(timer);
timer=$timeout(function(){
$http.get(url)
},200);
}
Upvotes: 0