Globaler Ajax-Fehlerbehandler mit AngularJS


82

Als meine Website zu 100% aus jQuery bestand, habe ich Folgendes getan:

$.ajaxSetup({
    global: true,
    error: function(xhr, status, err) {
        if (xhr.status == 401) {
           window.location = "./index.html";
        }
    }
});

um einen globalen Handler für 401-Fehler festzulegen. Jetzt verwende ich anglejs mit $resourceund $http, um meine (REST-) Anforderungen an den Server zu erledigen. Gibt es eine Möglichkeit, einen globalen Fehlerbehandler auf ähnliche Weise mit Angular festzulegen?


Ist es ein mögliches Duplikat von AngularJS Failed Resource GET ?
MilkyWayJoe

1
Nein, wir möchten einen globalen Fehler 401-Handler für die Anwendung
ausführen

lol, hast du dir überlegt, was du willst, aber mit einem anderen http-Status (den du ändern kannst)? Wie auch immer, die Antwort von pkozlowski.opensource zeigt Ihnen, wie es geht
MilkyWayJoe

Nein, es ist viel mehr wie die Antwort von Justen ... dies ist kein Duplikat mit der Frage, die Sie sprechen
Cricardol

Antworten:


97

Ich baue auch eine Website mit Winkel und bin auf dasselbe Hindernis für die globale 401-Handhabung gestoßen. Ich habe schließlich http interceptor verwendet, als ich auf diesen Blog-Beitrag gestoßen bin. Vielleicht finden Sie es genauso hilfreich wie ich.

"Authentifizierung in AngularJS (oder einer ähnlichen) basierten Anwendung." , Espeo-Software

EDIT: endgültige Lösung

angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives'], function ($routeProvider, $locationProvider, $httpProvider) {

    var interceptor = ['$rootScope', '$q', function (scope, $q) {

        function success(response) {
            return response;
        }

        function error(response) {
            var status = response.status;

            if (status == 401) {
                window.location = "./index.html";
                return;
            }
            // otherwise
            return $q.reject(response);

        }

        return function (promise) {
            return promise.then(success, error);
        }

    }];
    $httpProvider.responseInterceptors.push(interceptor);

4
Müssen $ q.reject (Antwort) zurückgeben; wenn status == 401, um einen lauten Winkelfehler zu vermeiden
s_t_e_v_e

1
@daniellmb. Es hängt davon ab, ob. Wenn Sie tatsächlich zu einer anderen Seite wechseln möchten, ändern Sie nicht nur die Ansicht, sondern sollten auch $ window verwenden. Wenn Ihre Anmeldeseite nur eine andere Ansicht und ein anderer Controller mit Ihrem Winkel ist, können Sie $ location.path
uriDium

1
@uriDium richtig mein Punkt war, die eckigen bereitgestellten Objekte zu verwenden, damit Sie verspotten und testen können.
Daniellmb

22
$ httpProvider.responseInterceptors ist jetzt veraltet. Siehe docs.angularjs.org/api/ng.$http#description_interceptors .
Quarzmo

1
Im Erfolg müssen Sie wie return response || $q.when(response);folgt zurückgeben, damit bei einer leeren Antwort auch ein Versprechen-Objekt zurückgegeben wird.
Ashish Gaur

77

Bitte beachten Sie, dass responseInterceptors mit Angular 1.1.4 veraltet sind. Unten finden Sie einen Auszug, der auf den offiziellen Dokumenten basiert und die neue Methode zur Implementierung von Interceptors zeigt.

$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
  return {
    'response': function(response) {
      // do something on success
      return response || $q.when(response);
    },

   'responseError': function(rejection) {
      // do something on error
      if (canRecover(rejection)) {
        return responseOrNewPromise;
      }
      return $q.reject(rejection);
    }
  };
});

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

So sieht es in meinem Projekt mit Coffeescript aus:

angular.module("globalErrors", ['appStateModule']).factory "myHttpInterceptor", ($q, $log, growl) ->
  response: (response) ->
    $log.debug "success with status #{response.status}"
    response || $q.when response

  responseError: (rejection) ->
    $log.debug "error with status #{rejection.status} and data: #{rejection.data['message']}"
    switch rejection.status
      when 403
        growl.addErrorMessage "You don't have the right to do this"
      when 0
        growl.addErrorMessage "No connection, internet is down?"
      else
        growl.addErrorMessage "#{rejection.data['message']}"

    # do something on error
    $q.reject rejection

.config ($provide, $httpProvider) ->
  $httpProvider.interceptors.push('myHttpInterceptor')

Sie haben jedoch keine xhr-Daten oder andere nützliche Informationen im responseError-Interceptor. Es ist sogar unbrauchbar zu entscheiden, ob es wiederherstellbar ist.
zw0rk

1
@ zw0rk Du wirst ... drinnen responseError, rejectionhat alles was du brauchst.
Langdon

Wird diese letzte Zeile $httpProvider...in einen config()Block eingeschlossen?
Delwin

In der Tat habe ich meine Antwort bearbeitet, um zu zeigen, wie ich es in meinem Projekt mit Coffeescript gemacht habe. Verwenden Sie js2coffee.org, wenn Sie es in Javascript bevorzugen.
MikeR

Sollten nicht alle Verweise auf responseunter der responseErrorFunktion tatsächlich Verweise auf sein rejection(oder sollte der Name des Parameters in geändert werden response?
Adam Nofsinger

16

Erstellen Sie die Datei <script type="text/javascript" src="../js/config/httpInterceptor.js" ></script>mit diesem Inhalt:

(function(){
  var httpInterceptor = function ($provide, $httpProvider) {
    $provide.factory('httpInterceptor', function ($q) {
      return {
        response: function (response) {
          return response || $q.when(response);
        },
        responseError: function (rejection) {
          if(rejection.status === 401) {
            // you are not autorized
          }
          return $q.reject(rejection);
        }
      };
    });
    $httpProvider.interceptors.push('httpInterceptor');
  };
  angular.module("myModule").config(httpInterceptor);
}());

@ThilakRaj Der obige Code sollte bei jeder http-Anfrage ausgeführt werden. Erstellen Sie also zwei Haltepunkte in Chrome, einen in der Zeile "Rückgabe" und einen in der Zeile "Rückgabe $ q.reject", um zu überprüfen, ob er ordnungsgemäß ausgeführt wird.
Jan-Terje Sørensen
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.