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

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

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

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


person user3391137    schedule 17.12.2015    source источник
comment
Просить готовый к использованию код или учебник не по теме. Если у вас есть какой-то код, который вы не понимаете, опубликуйте код и скажите, что вы не понимаете.   -  person JB Nizet    schedule 17.12.2015
comment
Но мне нужно больше пояснений по реализации кода.. - укажите части, для которых вам нужны пояснения. Поскольку этот вопрос запрашивает сторонние ресурсы или готовый к использованию код, который здесь не по теме. Кстати, я нахожу вопросительный знак после спасибо забавным.   -  person T J    schedule 17.12.2015
comment
Нужен учебник с реализацией   -  person user3391137    schedule 17.12.2015
comment
этот блог слишком стар. не используйте его. возможно, это поможет: stackoverflow.com/questions/18130808/   -  person Avi    schedule 17.12.2015
comment
Ищите перехватчики. Вам не нужен специальный сервис, который проверяет наличие повторяющихся запросов. У вас есть перехватчик, который отслеживает ожидающие запросы. Если один из них уже запущен, когда новый сделан, отклоните новый, перехватите его отклонение и верните обещание для использования позже. Когда исходный запрос отвечает от сервера, перехватив его, используйте его ответ для разрешения ваших ожидающих запросов, имитирующих успешный ответ. Таким образом, ваши вызовы $http не должны изменяться. Вы можете расширить конфигурацию $http, чтобы отказаться от такого поведения.   -  person ste2425    schedule 17.12.2015


Ответы (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
           })
       }
    }

}());
person ssuperczynski    schedule 17.12.2015
comment
Вы пропустили часть, где OP пишет до того, как предыдущий запрос даст ответ. Ваше решение работает только после возвращения первого ответа. - person AsGoodAsItGets; 14.02.2018

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

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

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

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

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

person andreico    schedule 10.10.2017
comment
Я удивлен, если часть, которую вы изменили, работает, потому что request не является допустимой переменной/объектом в блоке кода, где вы вызываете $q.reject(request). - person AsGoodAsItGets; 14.02.2018

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

person Armin Durakovic    schedule 17.12.2015
comment
Однако запрос все равно будет отправлен на сервер. Если только вы не вызовете $http с уже отклоненным тайм-аутом. - person ste2425; 17.12.2015
comment
Вы правы, @ste2425, я поместил в свой http-запрос timeout: canceler.promise,, и когда я хочу, чтобы запрос завершился, я просто запускаю canceler.resolve();. Я не уверен, что это лучшее решение, но оно сработало для меня. - person Armin Durakovic; 17.12.2015

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

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

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;
            }
        }
    }
    ]);
}
person VikasChauhan    schedule 17.04.2017
comment
Я пробовал это, и мои одновременные запросы получают нулевой результат. Как я могу вернуть ответ от других повторяющихся запросов? Это означает, что если у меня есть два вызова к конечной точке и один из них отменен, можем ли мы вернуть результаты предыдущего запроса? Спасибо. - person matsientst; 02.08.2017