2012-08-14 8 views
44

Ich habe eine Anwendung mit AngularJS und einem serverseitigen Back-End erstellt, die alle Anfragen in JSON-Form liefert. Jede Anfrage ist in einen JSON-Container eingebettet, der eine Datenvariable enthält, die die für die Anfrage spezifischen Daten enthält. Die anderen Daten, die verwendet werden, um den Status und die Kontrolle innerhalb der Anwendung zu behalten, prüfen auf Fehler und Erfolgsmeldungen und prüfen auf Sitzungsflags. Alle diese anderen Variablen werden mit jeder Anforderung bedient und zuerst überprüft, bevor die Datenvariable ist.

Im Moment habe ich eine Methode, um den Inhalt der JSON-Antwort zuerst und dann die Daten selbst zu untersuchen.

$http.get('something.json').success(function(response) { 
    var data = examineJSONResponse(response); 
    //do the data stuff 
}); 

Dies funktioniert und die examineJSONResponse wirft einen Blick auf den Code, und wenn etwas nicht in Ordnung ist, dann wirft er eine Ausnahme und lädt die Seite mit window.location.href.

Gibt es eine Möglichkeit, dass ich dies innerhalb AngularJS automatisieren kann, so dass jedes Mal, wenn ein $ http-Aufruf gemacht wird, dies überprüft und NUR den Inhalt der Datenvariablen als JSON-Antwort zurückgibt?

Antwort

85

Sie können die Antworten abfangen, indem Sie einen Interzeptor zu $httpProvider.interceptors mit Angular 1.1.4+ hinzufügen (siehe Dokumentation here Suche nach Interzeptoren).

Für einen bestimmten Inhaltstyp wie JSON können Sie möglicherweise Änderungen zurückweisen oder eine Ausnahme auslösen, selbst wenn der Aufruf erfolgreich war. Sie können die response.data modifizieren, dass auch hier, um Ihren Controller-Code übergeben werden erhalten:

myModule.factory('myHttpInterceptor', function ($q) { 
    return { 
     response: function (response) { 
      // do something on success 
      if(response.headers()['content-type'] === "application/json; charset=utf-8"){ 
       // Validate response, if not ok reject 
       var data = examineJSONResponse(response); // assumes this function is available 

       if(!data) 
        return $q.reject(response); 
      } 
      return response; 
     }, 
     responseError: function (response) { 
      // do something on error 
      return $q.reject(response); 
     } 
    }; 
}); 
myModule.config(function ($httpProvider) { 
    $httpProvider.interceptors.push('myHttpInterceptor'); 
}); 

HINWEIS: Hier ist die ursprüngliche Antwort ist für Versionen vor 1.1.4 (responseInterceptors mit kantigem veraltet wurden 1.1 0,4):

Vielleicht gibt es einen besseren Weg, aber ich denke, Sie etwas ähnliches wie this post mit dem hTTP-Antwort-Interceptor tun können (beschrieben here) (für einen bestimmten Inhaltstyp wie json), wo Sie möglicherweise ablehnen Änderungen oder th Zeile eine Ausnahme, obwohl der Aufruf erfolgreich war. Sie können die response.data ändern, die auch hier an Ihren Controller-Code übergeben wird.

myModule.factory('myHttpInterceptor', function ($q) { 
    return function (promise) { 
     return promise.then(function (response) { 
      // do something on success 
      if(response.headers()['content-type'] === "application/json; charset=utf-8"){ 
       // Validate response if not ok reject 
       var data = examineJSONResponse(response); // assumes this function is available 

       if(!data) 
        return $q.reject(response); 
      } 
      return response; 
     }, function (response) { 
      // do something on error 
      return $q.reject(response); 
     }); 
    }; 
}); 
myModule.config(function ($httpProvider) { 
    $httpProvider.responseInterceptors.push('myHttpInterceptor'); 
}); 
+0

Works:

angular.module('App', []) .factory('myHttp',['$http',function($http) { return function(url, success, failure) { $http.get(url).success(function(json) { var data = examineJSONResponse(json); data && data.success ? success() : failure(); }).error(failure); ); } }]); 

Und jetzt kann dies wie genannt werden. – matsko

+0

Wie registriere ich diesen Interceptor tatsächlich mit eckigen? –

+1

@MikeyCee Ich habe das Beispiel geändert, um die Registrierung des Interceptors einzuschließen. Hoffe das hilft! – Gloopy

7

Eine andere Lösung besteht darin, einen Dienst zu erstellen und diesen um die Variable $ http zu verwenden.

wie ein Zauber
myHttp(url, onSuccess, onFailure); 
+2

Ihr Code wird nicht ausgeführt, da der zweite Parameter der 'service'-Methode eine Konstruktorfunktion sein muss, wie in [this thread in der AngularJS-Mailingliste] (https://groups.google.com/forum/#) erläutert. ! msg/angular/56sdORWEoqg/b8hdPskxZXsJ). Ich denke, dass Sie wahrscheinlich "Fabrik" anstelle von "Service" tippen und das würde funktionieren. – tamakisquare

+0

Sie haben Recht. Es sollte eine "Fabrik" sein. Es ist jetzt aktualisiert. Vielen Dank. – matsko