Как предотвратить дублирование запросов $http в приложении AngularJS?

Мне нужно предотвратить повторную отправку одного и того же запроса в API, прежде чем предыдущий запрос даст ответ. Я нашел несколько решений. Но я не хочу отключать кнопку во время ожидания ответа, потому что в моем приложении больше вызовов API.

Мне действительно нужно что-то сделать в моем $ провайдере.config() . Я нашел способ здесь ( http://blog.codebrag.com/post/57412530001/preventing-duplicated-requests-in-angularjs).

Но мне нужно больше уточняющего кода. Любые ссылки на это приветствуются.

4 ответа

Допустим, у вас есть $http в вашем controller.js файл.

Много запросов к серверу

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

Всего один запрос к серверу, независимо от того, сколько раз вы будете вызывать этот метод:

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

Пример:

(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
           })
       }
    }

}());

Я хотел бы дополнить ответ @VikasChauhan, однако мне не хватает репутации, чтобы комментировать его ответ.

Его код прекрасно работает для меня, кроме той части, где он возвращает ноль. Это заставляет Angular бросать кучу ошибок повсюду.

Вместо нуля я просто отклоняю запрос:

return $q.reject(request);

Вот моя функция:

$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;
        }
    };
}
]);

Надеюсь, что это помогает другим людям.

В моем проекте я столкнулся с этой проблемой. Я нашел очень полезное рабочее решение здесь

И реализовал это внутри конфига:

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

Вы можете создать функцию для отмены первого http-запроса при вызове другого по нажатию кнопки. Вот ссылка, в которой используется функция $q.defer(), которая помогла мне в аналогичной проблеме: http://odetocode.com/blogs/scott/archive/2014/04/24/canceling-http-requests-in-angularjs.aspx

Другие вопросы по тегам