So legen Sie ein globales http-Timeout in AngularJs fest


76

Ich weiß, dass ich jedes Mal eine Zeitüberschreitung festlegen kann:

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

... aber ich möchte ein globales Timeout festlegen, um meinen Code trocken zu halten.


Ich denke, dafür gibt es tatsächlich einen Grund. Der Server hat normalerweise schnelle und langsame Endpunkte, und ich denke, das eckige Team wollte nicht, dass jeder das langsamstmögliche Timeout hat, selbst für Anrufe, die normalerweise schnell sein sollten
OlivierM

1
Sie können einen Dienst erstellen, der http-Anforderungen ausführt, Methoden, URLs und Daten sendet und darin die gewünschten Standardkonfigurationen implementiert. Es ist auch besser, die Domäne der URL einzuschließen und nur den Rest der URL zu übergeben, und sie werden angehängt die vollständige URL
Mohamed Selim

1
wie man Timeout für Post-Methode $http.post('path/to/service', {data:data});
einstellt

Antworten:


41

AKTUALISIERT : $ http berücksichtigt nicht die Standardeinstellung für das in httpProvider festgelegte Zeitlimit (siehe Kommentare). Mögliche Problemumgehung: https://gist.github.com/adnan-i/5014277

Ursprüngliche Antwort:

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

1
Sind Sie sicher, dass der obige Code funktioniert? Es sieht so aus, als ob das config.timeout beim Aufruf von sendReq nicht geändert wird: github.com/angular/angular.js/blob/master/src/ng/http.js#L550 Vergleichen Sie mit den Standardeinstellungen.mitCredentials einige Zeilen darüber wird auf die Standardeinstellung zurückgreifen.
Orjan

@orjan Nun, das oben genannte funktioniert nicht von selbst, wenn Sie danach fragen. Der Code zeigt nur eine Konfigurationsoption für Ihr eigenes Angular-Projekt. Weitere Informationen finden Sie in den Abschnitten "Festlegen von HTTP-Headern" und "Parameter" unter docs.angularjs.org/api/ng.$http
Stewie,

1
Mir ist das Konfigurationsbeispiel bekannt und ich weiß, dass der Code nicht alleine ausgeführt wird. Mir sind auch die Standardeinstellungen für Header und withCredentials bekannt. Aber ich glaube nicht, dass die Standardeinstellungen für das Timeout funktionieren. Ich habe eine jsfiddle erstellt: jsfiddle.net/RYDMM/4, die versucht, das Problem zu reproduzieren, aber es sieht so aus, als ob das Timeout jsonp überhaupt nicht beeinflusst
orjan

Hier ist eine Zusammenfassung, die zu erklären versucht, dass es nicht möglich ist, eine Standardzeitüberschreitung festzulegen
orjan

2
@orjan Du hast absolut recht. Ich habe mich auf die Dokumentation verlassen, um die Antwort zu geben, aber dies beweist erneut, dass Angular-Dokumente nicht als verlässlich anzusehen sind. Nachdem ich mir die Quelle angesehen habe ( github.com/angular/angular.js/blob/master/src/ng/http.js#L759 ), kann ich Ihre Ergebnisse bestätigen - es ist nicht möglich, mit $ httpProvider ein globales Timeout festzulegen. Standardeinstellungen. Vielen Dank, Orjan, für Ihren Fleiß. Ich werde meine Antwort aktualisieren, um meine Problemumgehung
Stewie

105

Dies ist mit blutenden Angular.js möglich (getestet mit Git Master 4ae46814ff).

Sie können den Request http Interceptor verwenden. So was.

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

Und dann in .config $ httpProvider injizieren und dies tun:

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

6
Funktioniert wie ein Zauber und sollte die akzeptierte Antwort sein, da es jetzt 2 Jahre später ist ....
Sebastian J.

2
Warum injizieren Sie aus Interesse $ rootScope und $ q? oder werden diese außerhalb des eingefügten Codes verwendet?
Ben Taliadoros

1
Wie gehen Sie damit um? Ich stelle fest, dass die Anfrage storniert wurde. Kann ich einen Listener dafür einstellen?
Ben Taliadoros

Die beste Antwort, die von der aktuellen Version nicht vollständig unterstützt wird. Bitte aktualisieren Sie Ihre Antwort, indem Sie die erste Zeile entfernen, in der es um die eckige Version geht
Nicolas Janel

5
config.timeout = config.timeout || 10000;
Alexander Atanasov

9

Danke für den Beitrag und das Update !!

Bei der Untersuchung dieses Problems speziell für $resourcedachte ich, ich würde näher auf das eingehen, was ich gefunden habe:

  • Dieses Problem wurde im Tracker protokolliert und in Winkel 1.1.5 wird die Weitergabe der Timeout-Eigenschaft an die $httpAnforderung unterstützt:

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

  • Für diejenigen von uns in früheren Versionen, insbesondere ich verwende Angular 1.0.6, ist es möglich, die Quelldatei für angle-resource.js in Zeile 396 zu bearbeiten. Dort finden Sie den Aufruf, $httpwo Sie die Timeout-Eigenschaft für alle selbst hinzufügen können Ressourcenanforderungen.

  • Da es nicht erwähnt wurde und ich die Lösung von Stewie testen musste, wird bei einem Timeout das Argument 'status' überprüft, um zwischen einem Fehler und einem Abbruch / Timeout zu unterscheiden. Es wird 0für Zeitüberschreitungen zurückkehren, anstatt zu sagen 404:

    $http.get("/home", { timeout: 100 })
    .error(function(data, status, headers, config){
            console.log(status)
        }
    
  • Da es nur wenige Fälle gibt, in denen ich ein Zeitlimit verwenden muss, anstatt es global festzulegen, verpacke ich die Anforderungen in eine $timeoutFunktion wie folgt:

    //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
+! für "die Art und Weise, zwischen einem Fehler und einem Abbruch / Timeout zu unterscheiden"
Bennett McElwee

1

Ich habe die gleiche Anforderung und verwende AngularJS 1.0.7. Ich habe mir den folgenden Code ausgedacht, da keine der oben genannten Lösungen für mich machbar erscheint (machbar in dem Sinne, dass das Timeout an einem Ort global sein soll). Grundsätzlich ich bin Maskierung der ursprünglichen http $ Methoden und Hinzufügen timeoutfür jede $httpAnforderung und andere zwingende Verknüpfung Methoden, wie get, post... so dass sie die neuen maskiert verwenden werden $http.

JSFiddle für folgenden Code:

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

    }]);

})();

Fügen Sie die Abhängigkeit vom obigen Modul hinzu und konfigurieren Sie das Zeitlimit durch Konfigurieren ngx$httpTimeoutProviderwie folgt:

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)

} ]);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.