Як встановити глобальний час очікування http у AngularJs


76

Я знаю, що можу встановити тайм-аут кожен раз:

$http.get('path/to/service', {timeout: 5000});

... але я хочу встановити глобальний тайм-аут, щоб мій код був сухим.


Я думаю, що насправді для цього є причина. Сервер, як правило, має швидкі та повільні кінцеві точки, і я припускаю, що команда команди не хотіла, щоб у всіх був найменший можливий тайм-аут навіть для дзвінків, які зазвичай повинні бути швидкими
OlivierM

1
Ви можете зробити службу, яка робить http-запити, відправляти її методом, URL-адресою та даними, і всередині неї реалізовувати будь-які конфігурації за замовчуванням, які вам потрібно, також краще включити домен URL-адреси та передати йому лише решту, і він додає їх повна URL-адреса
Мохамед Селім

1
як встановити час очікування для методу публікації$http.post('path/to/service', {data:data});
ganesh

Відповіді:


41

ОНОВЛЕНО : $ http не буде поважати налаштування за замовчуванням для часу очікування, встановіть його в httpProvider (див. Коментарі). Можливе рішення: https://gist.github.com/adnan-i/5014277

Оригінальна відповідь:

angular.module('MyApp', [])
  .config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.timeout = 5000;
}]);

1
Ви впевнені, що код вище працює? Схоже, що config.timeout не змінюється при виклику sendReq: github.com/angular/angular.js/blob/master/src/ng/http.js#L550 Порівняйте з defaults.withCredentials кілька рядків вище, що повернеться за замовчуванням.
orjan

@orjan Ну, вищезазначене не буде працювати само по собі, якщо це те, про що ви просите. Код просто показує варіант конфігурації для вашого власного проекту Angular. Для отримання додаткової інформації ви можете подивитися на «Налаштування HTTP - заголовки» і секції «Parameters» на docs.angularjs.org/api/ng.$http
Стьюї

1
Мені відомо про приклад конфігурації та про те, що код не працює самостійно. Я також знаю про за замовчуванням для заголовка та withCredentials. Але я не думаю, що за замовчуванням працює тайм-аут. Я створив jsfiddle: jsfiddle.net/RYDMM/4, намагаючись відтворити проблему, але схоже, що час очікування взагалі не впливає на jsonp
orjan

Ось суть, яка намагається пояснити, що неможливо встановити час очікування
orjan

2
@orjan Ви абсолютно праві. Я покладався на документальну відповідь, надаючи відповідь, але ще раз це доводить, що не потрібно покладатися на документи Angular. Подивившись на джерело ( github.com/angular/angular.js/blob/master/src/ng/http.js#L759 ), я можу підтвердити ваші висновки - неможливо встановити глобальний тайм-аут за допомогою $ httpProvider. за замовчуванням. Дякую orjan за вашу старанність. Я буду оновлювати мій відповідь , щоб запропонувати свій обхідний шлях: gist.github.com/adnan-i/5014277
Стьюї

105

Це можливо за допомогою angular.js, що перекриває край (протестовано на git master 4ae46814ff).

Ви можете використовувати перехоплювач http. Подобається це.

 angular.module('yourapp')
  .factory('timeoutHttpIntercept', function ($rootScope, $q) {
    return {
      'request': function(config) {
        config.timeout = 10000;
        return config;
      }
    };
 });

А потім у .config введіть $ httpProvider і зробіть так:

$httpProvider.interceptors.push('timeoutHttpIntercept');

6
Працює як шарм, і це має бути прийнятою відповіддю, оскільки це відбувається через 2 роки ....
Себастьян Дж.

2
Через інтерес, чому ви вводите $ rootScope і $ q? або вони використовуються поза кодом, який ви вставили?
Ben Taliadoros

1
Крім того, як ти з цим справляєтьсяш? Я помічаю, що запит скасовано, чи можу я встановити слухача для цього?
Бен Таліадорос

найкраща відповідь, яка не повністю підтримується фактичною версією. Будь ласка, оновіть свою відповідь, видаливши перший рядок про кутову версію
Nicolas Janel

5
config.timeout = config.timeout || 10000;
Олександр Атанасов

9

Дякуємо за допис та оновлення !!

Досліджуючи це питання спеціально для $resource, я подумав, що детальніше розповім про те, що я знайшов:

  • Ця проблема була зареєстрована в трекері, і в кутовій версії 1.1.5 є підтримка передачі властивості тайм-ауту до $httpзапиту:

https://github.com/angular/angular.js/issues/2190 http://code.angularjs.org/1.1.5/docs/api/ngResource.$resource

  • Для тих з нас, які працювали в попередніх версіях, зокрема я використовую angular 1.0.6, можна відредагувати вихідний файл для angular-resource.js у рядку 396, ви знайдете виклик, $httpкуди ви можете додати властивість тайм-ауту самостійно для всіх запити ресурсів.

  • Оскільки про це не згадувалось, і мені довелося протестувати рішення Стюї, коли виникає тайм-аут, спосіб визначити між помилкою та перериванням / тайм-аутом - перевірка аргументу "статус". Він повернеться 0до таймаутів замість сказати 404:

    $http.get("/home", { timeout: 100 })
    .error(function(data, status, headers, config){
            console.log(status)
        }
    
  • Оскільки є лише кілька випадків, коли мені потрібно використовувати тайм-аут на відміну від глобального встановлення, я обертаю запити у $timeoutфункцію, наприклад:

    //errorHandler gets called wether it's a timeout or resource call fails
    
    var t = $timeout(errorHandler, 5000);
    myResource.$get( successHandler, errorHandler )   
    function successHandler(data){
        $timeout.cancel(t);
        //do something with data...
    }
    
    function errorHandler(data){
        //custom error handle code
    } 
    

1
+! про "спосіб визначити між помилкою та перериванням / тайм-аутом"
Беннетт Макелві

1

У мене така сама вимога, і я використовую AngularJS 1.0.7. Я придумав наведений нижче код, оскільки жодне з перерахованих вище рішень не здається мені здійсненним (здійсненним у тому сенсі, що я хочу, щоб час очікування був загальним). В принципі, я м маскує оригінальні $ HTTP методи і додавання timeoutдля кожного $httpзапиту і відкидаючи інші методи швидкого доступу, як get, post... так , що вони будуть використовувати новий замаскований $http.

JSFiddle для коду нижче:

/**
 * @name ngx$httpTimeoutModule
 * @description Decorates AngularJS $http service to set timeout for each
 * Ajax request.
 * 
 * Implementation notes: replace this with correct approach, once migrated to Angular 1.1.5+
 * 
 * @author Manikanta G
 */
;(function () {
    'use strict';

    var ngx$httpTimeoutModule = angular.module('ngx$httpTimeoutModule', []);

    ngx$httpTimeoutModule.provider('ngx$httpTimeout', function () {
        var self = this;
        this.config = {
            timeout: 1000 // default - 1 sec, in millis
        };

        this.$get = function () {
            return {
                config: self.config
            };
        };
    });

    /** 
     * AngularJS $http service decorator to add timeout
     */
    ngx$httpTimeoutModule.config(['$provide',  function($provide) {

        // configure $http provider to convert 'PUT', 'DELETE' methods to 'POST' requests
        $provide.decorator('$http', ['$delegate', 'ngx$httpTimeout', function($http, ngx$httpTimeout) {
            // create function which overrides $http function

            var _$http = $http;

            $http = function (config) {
                config.timeout = ngx$httpTimeout.config.timeout;
                return _$http(config);
            };
            $http.pendingRequests = _$http.pendingRequests;
            $http.defaults = _$http.defaults;

            // code copied from angular.js $HttpProvider function
            createShortMethods('get', 'delete', 'head', 'jsonp');
            createShortMethodsWithData('post', 'put');

            function createShortMethods(names) {
                angular.forEach(arguments, function(name) {
                    $http[name] = function(url, config) {
                        return $http(angular.extend(config || {}, {
                            method : name,
                            url : url
                        }));
                    };
                });
            }

            function createShortMethodsWithData(name) {
                angular.forEach(arguments, function(name) {
                    $http[name] = function(url, data, config) {
                        return $http(angular.extend(config || {}, {
                            method : name,
                            url : url,
                            data : data
                        }));
                    };
                });
            }

            return $http;
        }]);

    }]);

})();

Додайте залежність від вищевказаного модуля та налаштуйте час очікування, налаштувавши ngx$httpTimeoutProvider, як показано нижче:

angular.module('App', ['ngx$httpTimeoutModule']).config([ 'ngx$httpTimeoutProvider', function(ngx$httpTimeoutProvider) {
    // config timeout for $http requests
    ngx$httpTimeoutProvider.config.timeout = 300000; // 5min (5 min * 60 sec * 1000 millis)

} ]);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.