Restricting or postponing HTTP requests in an AngularJS service

I recently developed a service for my AngularJS app that retrieves data by making $http calls through various methods. However, I encountered an issue where these requests were being triggered every time an HTML element in the view (a product details div) became visible in the viewport due to lazy loading. This led to multiple simultaneous requests (approximately 50-60), causing performance degradation and potential blocking of other requests or the entire application. To address this problem, I needed to implement a mechanism to limit, restrict, queue, or delay the requests - with queuing being the preferred solution. For now, I decided to manage the request volume within the service.

This is how I invoke the service in my controllers/directives:

productAvailabilityService.getAvailability(scope.productId).then(function (result) {
    // handle the result... 
});

Here's the initial service implementation:

.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 aim to incorporate limiting functionality as follows:

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

However, implementing this approach resulted in the error message "getAvailability(...).then is not a function" when the number of requests exceeded 6. I am struggling to resolve this issue. Additionally, I acknowledge that my current method may not be the best way to control the frequency of invoking a service or executing $http requests. I welcome any suggestions or advice on improving this process. Thank you in advance!

Answer №1

It is important to utilize a promise for the productAvailabilityService. Returning a function instead of a promise can cause an error when using "then()" in the code.

Below is a snippet of code demonstrating the use of a 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.

Alternatively, you may consider implementing the resolve function for managing delayed calls.

Answer №2

Implementing DelayHttp for Better Request Handling

app.factory('DelayHttp', ($http, $timeout) => {
    let counter = 0,
        delay = 100;

    return (conf) => {
        counter += 1;

        return $timeout(() => {
            counter -= 1;
            return $http(conf);
        }, counter * delay);
    };
});

How to Use:

return DelayHttp({
    url: url,
    method: 'GET',
    params: params
});

This feature queues and executes requests with a 100ms interval or a maximum of 10 requests per second. Feel free to adjust the delay based on your desired throughput.

Answer №3

To ensure the user has enough time to access the content they desire before making requests, I recommend setting a time interval like this:

 var timer;
 function fetchData(){
          $timeout.cancel(timer);
          timer=$timeout(function(){
                $http.get(url)
          },200);
 }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transferring an Applescript list to ExtendScript in Javascript as an array for use in InDesign

Situation Background I have a large number of Applescripts (AS) that designers rely on in InDesign to streamline production workflows. These AS scripts handle a lot of OS interactions that JavaScript cannot replicate, so transitioning away from AS is not ...

Fixing a CSS animation glitch when using JavaScript

I'm facing an unusual issue with my CSS/HTML Check out my code below: a:hover { color: deeppink; transition: all 0.2s ease-out } .logo { height: 300px; margin-top: -100px; transition: all 0.2s ease-in; transform: scale(1) } .logo:hover { transit ...

Attempting to include a select element via transclusion

Looking to develop a custom directive named select that will replace a select element with a customized dropdown interface. For a clear example, check out this jsfiddle where the concept is demonstrated. Let's consider the below select element: < ...

I'm having trouble figuring out how to access response headers with HttpClient in Angular 5. Can anyone

I recently developed an authentication service in Angular 5, where I utilize the HttpClient class to make a POST request to my backend server. The backend server then responds with a JWT bearer token. Here is a snippet of how my request looks: return thi ...

Setting up Vue CLI 4 with ESLint, TypeScript, Stylelint for SCSS, and Airbnb rules in the VS Code editor with automatic fixes on save

After struggling with configuring Vue CLI 4 with ESLint, Prettier, Airbnb rules, TypeScript, and Vetur, I found myself at a crossroads. The challenges continued to mount as the nature of the problem evolved from my previous attempts.: How to configure Vue ...

Encountering issues with link button redirection

I have a question regarding a Link element and CustomButton element with an onClick handler. < Link to = "/dashboard" style = { linkStyles } > < CustomButton text = "Login" onClick = { handleSubmit } /> < /Link> The code ...

What is the procedure for transferring the inputted data from an HTML file to its corresponding TS file and subsequently to a different component file?

I have created two components, a login and a home-page. I am attempting to capture user input from the login template, pass it to the login component, and then display it on the home-page template using the home-page component. What is the best approach to ...

Mastering socket emission and disconnection in reactjs

When using the onchange function, I am able to open a socket and emit/fetch data successfully. However, a new socket is opened on any event. I need to find a way to emit data from the same socket ID without opening a new socket each time. Could you pleas ...

Setting the x-api-key header with HttpInterceptor in Angular 4: A guide

I am attempting to use HttpInterceptor to set the header key and value, but I am encountering the following error: Failed to load https://example.com/api/agency: Response to preflight request doesn't pass access control check: No 'Access ...

Managing data from devices by using Ionic v2 along with the BLE Central plugin

Currently experiencing some difficulties when it comes to managing the device data of discovered peripherals. I am searching for some guidance on this matter. I can successfully scan for devices and my "success" callback functions without any issues. My g ...

Adding ngSanitize as a dependency causes the app to malfunction

Whenever I integrate ngSanitize into my Angular application, it seems to disrupt the system's functionality. Here is the setup for adding ngSanitize: angular.module('routings', ['ngSanitize']).controller('RoutingsController& ...

AngularJS - retrieving and displaying the selected value from an HTML dropdown menu

Could someone help me figure out why the Land selection is empty when trying to display it as {{ selectCenter.land }}? For reference, here is a functional plunker: http://plnkr.co/edit/Q8jhdJltlh14oBBLeHJ9?p=preview And the relevant code snippet: ...

Could it be that the AmCharts Drillup feature is not fully integrated with AngularJS?

UPDATE: Check out this Plunker I created to better showcase the issue. There seems to be an issue with the Back link label in the chart not functioning as expected. I'm currently facing a challenge with the AmCharts Drillup function, which should a ...

Harnessing the power of custom directives in HTML

I have developed a custom directive that adds the active class to the clicked li element in the menu list based on the URL. .directive('addActive', [function() { return{ ... link : function(scope, element, attrs){ ...

How to verify the parent nodes in a jstree

I have implemented a two state jstree. However, I am encountering an issue where it is not possible to select any other node in relation to a node. My goal is that when I click on a specific node, all of its parent nodes should also be checked. Any assist ...

Exploring object properties within arrays and nested objects using ReactJS

Within the react component PokemonInfo, I am looking to extract the stats.base_stat value from the JSON obtained from https://pokeapi.co/api/v2/pokemon/1/. The issue lies in the fact that base_stat is nested inside an array called stats. My assumption is t ...

tips for implementing JSON loading in Ext JS

While attempting to load values from a web service, I encountered the following error message: "ChatStore.data.items[i] is undefined." The mapping code for extjs is as follows: ChatStore = new Ext.data.JsonStore({ storeId: 'ChatStore1' ...

The Access-Control-Allow-Origin error is preventing the Angularjs post request from going through

I am encountering an issue with my index.html file that is sending a post request to localhost:3000/SetUser. The error I keep receiving states XMLHttpRequest cannot load https://localhost:3000/SetUser. No 'Access-Control-Allow-Origin' header is p ...

Utilize a fluid AJAX endpoint for the Vue Select2 encapsulated component

I have customized the Wrapper Component Example based on VueJS documentation by adding the AJAX data source feature. You can view my modified code here. My goal is to dynamically set the ajax url property of my select2 component, like this: <select2 :o ...

Is there a way to send an array of objects to my Express / SQL Server in react?

I am currently facing a challenge with passing an array of objects to my back end (SQL Server). Below is the specific array of objects: console.info(results) Here is the array of objects named results: [0] [ [0] { [0] answer: 'bmbm,nn', [ ...