3

I need to prevent sending the same request repeatedly to API before the previous request will give the response. I have found out some solutions. But, I don't want to disable the button while waiting for response because I have more API calls in my app.

I really need to do something in my $provider .config() .I found a way here(http://blog.codebrag.com/post/57412530001/preventing-duplicated-requests-in-angularjs).

But I need more clarification code. Any kind of reference about this is welcome.

5
  • 1
    Asking for ready to use code or for a tutorial is off-topic. If you have some code that you don't understand, then post the code, and tell what you don't understand. Commented Dec 17, 2015 at 7:38
  • "But i need more clarification code implementation.." - please quote the parts that you need clarification for. As it is this question is asking for offsite resources or ready to use code which is off-topic here. BTW, I find the question mark after "thanks" funny. Commented Dec 17, 2015 at 7:45
  • Needs tutorial with implementation Commented Dec 17, 2015 at 7:56
  • this blog is too old. don't use it. maybe this will help: stackoverflow.com/questions/18130808/… Commented Dec 17, 2015 at 8:02
  • Look up interceptors. You do not need a custom service that checks if there are duplicate requests. You have an interceptor that keeps track of pending requests. If one is already running when a new one is made reject the new one, catch its reject and return a promise to use later. When the original request responds from the server intecept it, use its response to resolve your waiting requests mimicking a successful response. This way your calls to $http don't need to change. You could extend the $http config to opt out of this behavior. Commented Dec 17, 2015 at 8:33

4 Answers 4

2

Lets say you have $http in your controller.js file.

Many request to server

$http.get('/link/to/file.php');

Just one request to server, no matter how many times you will call this method:

$http.get('/link/to/file.php', {cache: true});

Example:

(function() {
    'use strict';

    angular
            .module('yourModuleName')
            .controller('DashboardCtrl', DashboardCtrl);

    DashboardCtrl.$inject = ['$scope'];

    function DashboardCtrl($scope) {

       $scope.get = function () {
           $http.get('/link/to/file.php', {cache: true}).then(function(response) {
               // it will do GET request just once
               // later you will get the same response from cacheFactory
           })
       }
    }

}());
Sign up to request clarification or add additional context in comments.

1 Comment

You missed the part where the OP writes "before the previous request will give the response". Your solution only works after the first response has returned.
1

I would like to complement @VikasChauhan answer, however I do not have enough reputation to comment on his answer.

His code works great for me, except the part where he returns null. That causes Angular to throw a bunch of errors all over.

Instead of null, I simply reject the request:

return $q.reject(request);

Here's my function:

$httpProvider.interceptors.push(['$injector', '$q', function interceptors($injector, $q) {
    return {
        // preventing duplicate requests
        request: function request(config) {
            var $http = $injector.get('$http');
            var _config = angular.copy(config);
            delete _config.headers;

            function isConfigEqual(pendingRequestConfig) {
                var _pendingRequestConfig = angular.copy(pendingRequestConfig);
                delete _pendingRequestConfig.headers;

                return angular.equals(_config, _pendingRequestConfig);
            }

            if ($http.pendingRequests.some(isConfigEqual)) {
                return $q.reject(request);
            }

            return config;
        }
    };
}
]);

Hope this helps other people.

1 Comment

I'm surprised if the part that you changed works, because request is not a valid variable/object in the block of code where you're calling $q.reject(request).
0

You can create a function to cancel the first http request, when calling the another one on the button click. Here is a reference that uses $q.defer() function that helped me on a similar issue: http://odetocode.com/blogs/scott/archive/2014/04/24/canceling-http-requests-in-angularjs.aspx

2 Comments

The request will still be made to the server however. Unless you call $http with a already rejected timeout.
You are right @ste2425, I put inside my http request timeout: canceler.promise,, and when I want the request to end, I just run canceler.resolve();. I'm not sure if it's the best solution, but it worked for me.
0

In my project, i was facing this problem. I found a very useful working solution here

And implemented it inside the config:

function config($routeProvider, $httpProvider) {

    $httpProvider.interceptors.push(['$injector', function interceptors($injector) {
        // Manually injecting dependencies to avoid circular dependency problem
        return {
            // preventing duplicate requests
            'request': function request(config) {
                var $http = $injector.get('$http'),
                copiedConfig = angular.copy(config);

                delete copiedConfig.headers;
                function configsAreEqual(pendingRequestConfig) {
                    var copiedPendingRequestConfig = angular.copy(pendingRequestConfig);

                    delete copiedPendingRequestConfig.headers;

                    return angular.equals(copiedConfig, copiedPendingRequestConfig);
                }

                if ($http.pendingRequests.some(configsAreEqual)) {
                    debugger;
                    return null;
                }

                return config;
            }
        }
    }
    ]);
}

1 Comment

I tried this and my concurrent requests get a result of null. How can I return the response from the other duplicate requests? Meaning, if I have two calls to an endpoint and one get's cancelled, can we return the results of the previous request? Thx.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.