Tipps und Tricks für AngularJS, Teil 5: Transformationen und Interceptors

Know-how  –  0 Kommentare

Transformationsfunktionen und Interceptors sind mächtige Konzepte zum Beeinflussen der Kommunikation zwischen AngularJS-Anwendungen und HTTP-Ressourcen. Gemäß dem DRY-Prinzip (Don't repeat yourself) helfen sie bei der zentralen Umsetzung von Querschnittsfunktionen.

Der $http-Service ist wohl einer der meistgenutzten Dienste in AngularJS-Projekten. Gerade für seine Standardaufgabe, Daten im JSON-Format via HTTP zu senden beziehungsweise abzurufen, ist er vergleichsweise einfach zu nutzen. Doch unter seiner Haube finden sich komplexe, durchdachte Konzepte, die Entwicklungsteams zusätzliche Freiheiten geben.

Zu ihnen gehören Transformationsfunktionen und Interceptors. Erstere nutzt $http zum Serialisieren und Deserialisieren von Daten. Letztere bieten Einsprungspunkte zum Realisieren weiterer Querschnittsfunktionen, was unter anderem für globale Fehlerbehandlungen nützlich ist. Der vorliegende Beitrag geht sowohl auf Transformationsfunktionen als auch auf das Interceptor-Konzept ein. Die dazu genutzten Beispiele stellt der Autor auf GitHub zur Verfügung.

Anfragen transformieren

Standardmäßig nutzt AngularJS Transformationsfunktionen zum Serialisieren beziehungsweise Deserialisieren von Daten im JSON-Format. Während sich die Funktion transformRequest um das Serialisieren von Anfragen kümmert, kommt transformResponse beim Deserialisieren von Antworten zum Einsatz. Durch das Bereitstellen eigener Implementierungen können Entwickler zudem andere Datenformate nutzen.

Eine Implementierung, die XML statt JSON nutzt, ist beispielsweise angular-xml. Da der Fokus des vorliegenden Artikels auf der Erklärung der dahinterstehenden Konzepte liegt, geht er auf eine vereinfachte Umsetzung der Marke Eigenbau ein. Sie nutzt das freie Projekt X2JS, das Funktionen zum Konvertieren zwischen JavaScript-Objekten, JSON und XML anbietet. Entwickler können es beispielsweise via Bower beziehen:

bower install x2js

Anschließend ist die Skriptdatei xml2json.min.js in das aktuelle Projekt einzubinden:

<script src="scripts/x2js/xml2json.min.js"></script>

Die genutzte transformRequest-Funktion sieht wie folgt aus:

this.buchenXML = function () {
var that = this;

var transformXmlRequest = function(data, headersGetter) {

var headers = headersGetter();
var contentType = headers["Content-Type"];

if (contentType.indexOf("xml") !== -1) {
var x2js = new X2JS();
var xmlString = x2js.json2xml_str(data);
return xmlString;
}
return data;

}

var options = {
transformRequest: transformXmlRequest,
headers: {
"Content-Type": "text/xml"
}
};

var buchung = {
Buchung: {
"_xmlns": "http://schemas.datacontract.org/2004/07/
SVC.Controllers",
flugID: that.selectedFlug.id,
passagierID: that.selectedPassagier.id
}
};

$http.post(baseUrl + "/api/buchung", buchung,
options).then(function (result) {
that.message = "Gebucht!";
}).catch(function (reason) {
that.message = "Fehler beim Buchen des Flugs: "
+ reason;
});
};

Sie nennt sich transformXmlRequest und bezieht die zu serialisierenden Daten über den Parameter data. Durch Aufruf der übergebenen Funktion headersGetter erhält sie ein Objekt mit den zu übersendenden Kopfzeilen. Zeigt der dort hinterlegte Eintrag für den Content-Type an, dass XML-Daten zu verwenden sind, wandelt sie das Objekt in XML um. Dazu nutzt die Funktion das Objekt X2JS aus dem gleichnamigen Projekt. Dessen Funktion json2xml_str nimmt das JavaScript-Objekt entgegen und liefert einen XML-String zurück. Er stellt auch das endgültige Ergebnis von transformXmlRequest dar.

Geht hingegen aus dem Content-Type-Eintrag hervor, dass nicht XML sondern ein anderes Format gewünscht ist, liefert transformXmlRequest den Wert von data ohne Modifikation zurück. Somit erhält eine eventuell vorhandene weitere transformRequest-Funktion die Möglichkeit, die ausgehenden Daten zu serialisieren.

Anschließend versendet die im Beispiel gezeigte Anwendung via $http ein Objekt namens buchung. Da es transformXmlRequest über das Options-Objekt als transformRequest-Funktion bekannt gibt, nutzt $http sie zur Serialisierung. Den zu verwendenden XML-Namensraum entnimmt X2JS der Eigenschaft _xmlns.

Möchten Entwickler bei jedem Aufruf eine Funktion transformRequest nutzen, können sie sie auch bei $http oder $httpProvider registrieren. Dazu stellen die Dienste ein Array $http.defaults.transformRequest beziehungsweise $httpProvider.defaults.transformRequest zur Verfügung. Standardmäßig findet sich dort eine Funktion, die das zu versendende Objekt in eines im JSON-Format umwandelt.