4

I'm looking for a AngularJS-based way to prevent multiple submits per task.

I don't need buttons to be disabled after submission or close the form and wait for the task to be completed. Instead, I need requests to be unique.

To be more detailed, I need $http.get and $http.post stop sending multiple same requests.

Any Ideas?

1
  • I think best way will be to maintain a array in which you will store particular api's uri key say for eg. key - 1 for www.xyz.com/xyz and key 2- for www.xyz.com/abc, now before calling any api check if its present on array if yes then do not call api again.On success remove api key from array. Commented Nov 10, 2015 at 7:12

2 Answers 2

4

According to this article, you can use provider decorator.
NOTE: this approach is based on angular-api
https://gist.github.com/adambuczynski/354364e2a58786e2be71


UPDATE

I've changed a little part in your suggested solution, because returned promises have lost .success and .error and .then. Just use this edited code to have all of those functions working:

    .config(["$provide", function ($provide) {
    $provide.decorator('$http', function ($delegate, $q) {

        var pendingRequests = {};
        var $http = $delegate;

        function hash(str) {
            var h = 0;
            var strlen = str.length;
            if (strlen === 0) {
                return h;
            }
            for (var i = 0, n; i < strlen; ++i) {
                n = str.charCodeAt(i);
                h = ((h << 5) - h) + n;
                h = h & h;
            }
            return h >>> 0;
        }

        function getRequestIdentifier(config) {
            var str = config.method + config.url;
            if (config.data && typeof config.data === 'object') {
                str += angular.toJson(config.data);
            }
            return hash(str);
        }

        var $duplicateRequestsFilter = function (config) {

            if (config.ignoreDuplicateRequest) {
                return $http(config);
            }

            var identifier = getRequestIdentifier(config);

            if (pendingRequests[identifier]) {
                if (config.rejectDuplicateRequest) {
                    return $q.reject({
                        data: '',
                        headers: {},
                        status: config.rejectDuplicateStatusCode || 400,
                        config: config
                    });
                }
                return pendingRequests[identifier];
            }

            pendingRequests[identifier] = $http(config);

            $http(config).finally(function () {
                delete pendingRequests[identifier];
            });

            return pendingRequests[identifier];
        };

        Object.keys($http).filter(function (key) {
            return (typeof $http[key] === 'function');
        }).forEach(function (key) {
            $duplicateRequestsFilter[key] = $http[key];
        });

        return $duplicateRequestsFilter;
    })
}])
Sign up to request clarification or add additional context in comments.

1 Comment

It is actually implemented as same as I posted in the answer, But with speed optimization with hash creation from JSON Data. Very Useful.
0

It could be a performance issue but following idea could solve your problem.

Store the each request URL and DATA as key value pair on a variable. URL should be KEY. For Same URL multiple submission can be stored in a Array.

Then for any new call check the URL if it present in your stored object, then compare the data with each object thorughly (deep check, it is costly though). If any exact match found then stop the processing. As same request came. Other wise proceed and don't forget to store this data also.

But it is costly since need to check the data which could be havy.

Note: At the time of storing the data you could convert it to JSON String so it will be easier to compare between String.

here is the Code Algo

YourService.call(url, params) {
    var Str1 = JSON.stringify(params);
    if(StoredObj[url]) {
        for each (StoredObj[url] as Str){
             if(Str === Str1) {
               return;
             }
        }
    }
    else {
       StoredObj[url] = []; //new Array
    }
    StoredObj[url].push(Str1);
    Call $http then;
}

1 Comment

Thanks for your suggestion. please see the approved solution.

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.