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

Troubleshooting a shadow mapping problem in three.js involving a ShaderMaterial that alters the positions of vertices

Within my current project, I have implemented a ShaderMaterial to depict terrains. The positions of the vertices are adjusted in the vertex shader based on information from a height map texture: vec4 mvPosition = modelViewMatrix * vec4( position + normal ...

Encountered a TypeError with mongoose: The function specified is not recognized as a valid function when attempting to create a new mongoose instance

I'm currently developing a web application using the MEAN stack, and I've encountered an issue with my mongoose instance that's giving me a headache. Let me share parts of my code: my route const express = require('express'); co ...

react-query: QueryOptions not functioning as expected when utilizing userQueries()

When passing certain "query options" while using useQueries() to fetch multiple queries simultaneously, these specified "query options" do not get applied during query executions (e.g. refetchOnWindowFocus has a value of true but I want it to be false). F ...

Passing $index variable from a bootstrap modal window does not work in AngularJS

I'm running into a wall here. My issue involves using ng-repeat to populate a table with two buttons in each row - one for updating the row content and another for uploading files. The upload button triggers a bootstrap modal window where users can se ...

How to retrieve an unknown JSON key in Vue.js when using v-for loop?

I have developed a code analysis tool and I am looking to display my JSON data in a Vue table. The challenge is that I need the JSON key, which represents the package/file name of the directory whose data I want to showcase. Below is an excerpt of the JSO ...

Exploring dependency injection in Angular 1 using a blend of JavaScript and TypeScript

I'm currently working on integrating TypeScript into an existing Angular 1.5 application. Despite successfully using Angular services and third-party services, I am facing difficulties in injecting custom services that are written in vanilla JavaScrip ...

What is the method for determining the gaps between cells in a grid-based puzzle game similar to Sudoku?

this is my current code and it's successfully functioning var cellSize:Number = 36; var cellGap:Number = 4; var row:Number; var col:Number; for (var a:int = 0 ; a < puzzleSTR.length ; a++) { col = a % 9; row = Math.floor(a / 9); ...

Error: Unable to access the 'nom_gr' property of null - encountered in Chrome

<ion-col col-9 class="sildes"> <ion-slides slidesPerView="{{nbPerPage}}" spaceBetween="5"> <ion-slide *ngFor="let slide of lesClassrooms; let i = index" (click)="saveCurrentSlide(i)"> ...

Is it possible to modify the numerical values within TimeCircles.js?

I have integrated the TimeCircles.js plugin into a Persian website and need to convert Persian numbers to English. I already have a function that replaces each digit with the appropriate English number. I am able to successfully convert the text inside t ...

Is it possible to trigger the @click event in Vuejs when utilizing v-html to render HTML content?

Here is an interesting HTML scenario: errorText: '<a class="button" @click.prevent="enableExceedable(issue.mapping)">Enable exceedable limits</a>'; I am trying to insert this string into the following div: <div v-if="hasIssue != ...

My pen doesn't accurately display the ID

CHALLENGE var shoppingCenters = [{ id: 0, name: 'Leclerc', location: 'Paris,France', address:'Boulevard Rahal El Meskini Casablanca Maroc', ] }, { /*Malls B*/ id: 1, name: 'Carefour', location ...

Trouble accessing data property within a method in Vue 3 with Typescript

I am facing an issue with accessing my data in a method I have written. I am getting a Typescript error TS2339 which states that the property does not exist in the type. TS2339: Property 'players' does not exist on type '{ onAddPlayers(): vo ...

The issue persists with the ajax.reload() function in DataTables

It's been driving me crazy that my datatables table won't refresh, despite using ajax.reload. I've spent weeks on this code but still can't get it to work. DataTablesDraw = (selector, order, pages, file, sort, column, template, data_se ...

What is the correct way to properly deploy Nuxt.js in SPA mode on a server?

My current project involves utilizing Nuxt.js in Single Page Application (SPA) mode. However, I am encountering difficulties when trying to deploy it on my Apache server. Has anyone else faced this issue before? I suspect that the problem may be related t ...

"Utilizing jQuery to Trigger CSS3 Transform Animation Replays After a Set Number of Iterations

I currently have an animated image set up like this: <div class="image_for_sping"> <img src="/anyimage.png"> </div> The image has a style attribute added by jQuery which contains the following animation properties: animation: spin3 ...

Having trouble making class changes with ng-class

I am attempting to change the direction of the arrow in my checkbox by utilizing two classes with the assistance of ng-class. Unfortunately, it is not producing the desired outcome. Below is my code: Note: The angularJS CDN has already been incorporated. ...

What steps can be taken to enhance cleanliness and efficiency, and what are some recommended practices to adhere to?

Currently, I am in the process of developing a user authentication system on the backend. Specifically, I have implemented a POST method for registering new users. userRouter.post("/", expressAsyncHandler(async (req, res) => { try { const { na ...

Having trouble retrieving state parameters when trying to launch a modal in AngularJS

When the "view detail" link is clicked, I wanted to open a modal for a detailed view of a specific user. However, I encountered an issue where I couldn't retrieve the user ID in the resolve attribute of $uibModal.open(). Strangely enough, the ID is av ...

The callback function inside the .then block of a Promise.all never gets

I'm currently attempting to utilize Promise.all and map in place of the forEach loop to make the task asynchronous. All promises within the Promise.all array are executed and resolved. Here is the code snippet: loadDistances() { //return new Prom ...

Utilizing an EJS template within an express.js application to extract and assign data to a variable

Is there a way to transfer data from my node.js (express) app directly to a variable within the <script> tag on the page? On the server-side, I have the following code: let tmp = JSON.stringify(await f(i)); console.log(tmp); //correct data [{"i ...