HTTP-Anfragen sind ein wichtiger Bestandteil jeder Webanwendung, die mit einem Back-End-Server kommuniziert. Das Frontend benötigt einige Daten, fragt diese über eine Netzwerk-HTTP-Anfrage (oder Ajax, wie es oft genannt wird) an, und der Server liefert eine Antwort. Fast jede Website macht dies heutzutage in irgendeiner Form.
Bei einer größeren Website können wir mehr davon erwarten. Mehr Daten, mehr APIs und mehr Sonderfälle. Wenn Websites so wachsen, ist es wichtig, organisiert zu bleiben. Ein klassisches Konzept ist DRY (kurz für Don't Repeat Yourself), was der Prozess der Abstraktion von Code ist, um zu verhindern, dass er immer wieder wiederholt wird. Das ist ideal, da es uns oft ermöglicht, etwas einmal zu schreiben, es an mehreren Stellen zu verwenden und es an einer einzigen Stelle zu aktualisieren, anstatt an jeder einzelnen Instanz.
Wir können uns auch an Bibliotheken wenden, um uns zu helfen. Für Ajax ist axios eine beliebte Wahl. Möglicherweise sind Sie bereits damit vertraut und verwenden es sogar für Dinge wie unabhängige POST- und GET-Anfragen während der Entwicklung.
Installation und die Grundlagen
Es kann mit npm (oder yarn) installiert werden
npm install axios
Eine unabhängige POST-Anfrage mit Axios sieht so aus
axios.post('https://axios-app.firebaseio.com/users.json', formData)
.then(res => console.log(res))
.catch(error => console.log(error))
Native JavaScript hat auch mehrere Möglichkeiten, JavaScript zu machen. Insbesondere fetch(). Warum also überhaupt eine Bibliothek verwenden? Nun, zum einen ist die Fehlerbehandlung in fetch ziemlich umständlich. Mit axios werden Sie damit von Anfang an eine bessere Erfahrung haben. Wenn Sie einen Vergleich sehen möchten, haben wir einen Artikel, der beide behandelt und einen Artikel, der über den Wert von Abstraktionen bei solchen Dingen spricht.
Ein weiterer Grund, zu axios zu greifen? Es bietet uns mehr Möglichkeiten für DRYness, also schauen wir uns das mal an.
Globale Konfiguration
Wir können eine globale Konfiguration einrichten (z. B. in unserer main.js-Datei), die alle Anwendungsanfragen über **eine Standardkonfiguration** abwickelt, die über ein Standardobjekt gesetzt wird, das mit axios geliefert wird.
Dieses Objekt enthält
baseURL:Eine relative URL, die als Präfix für alle Anfragen dient, und jede Anfrage kann die URL anhängenheaders: Benutzerdefinierte Header, die basierend auf den Anfragen gesetzt werden könnentimeout:Der Zeitpunkt, an dem die Anfrage abgebrochen wird, normalerweise in Millisekunden gemessen. Der Standardwert ist0, was bedeutet, dass er nicht anwendbar ist.withCredentials: Gibt an, ob Cross-Site-Access-Control-Anfragen mit Anmeldeinformationen durchgeführt werden sollen. Der Standardwert istfalse.responseType: Gibt den Datentyp an, den der Server zurückgibt, mit Optionen wiejson(Standard),arraybuffer,document,textundstream.responseEncoding: Gibt die zu verwendende Kodierung für die Dekodierung von Antworten an. Der Standardwert istutf8.xsrfCookieName: Der Name des Cookies, der als Wert für das XSRF-Token verwendet wird, der Standardwert istXSRF-TOKEN.xsrfHeaderName: Der Name des HTTP-Headers, der den XSRF-Token-Wert trägt. Der Standardwert istX-XSRF-TOKEN.maxContentLength: Definiert die maximal zulässige Größe des HTTP-Antwortinhalts in BytesmaxBodyLength: Definiert die maximal zulässige Größe des HTTP-Anfrageinhalts in Bytes
Meistens werden Sie nur baseURL, header und vielleicht timeout verwenden. Die restlichen sind seltener nötig, da sie intelligente Standardwerte haben, aber es ist gut zu wissen, dass sie vorhanden sind, falls Sie Anfragen korrigieren müssen.
Das ist die DRYness in Aktion. Für jede Anfrage müssen wir nicht die baseURL unserer API wiederholen oder wichtige Header wiederholen, die wir bei jeder Anfrage benötigen könnten.
Hier ist ein Beispiel, bei dem unsere API eine Basis hat, aber auch mehrere verschiedene Endpunkte. Zuerst richten wir einige Standardwerte ein
// main.js
import axios from 'axios';
axios.defaults.baseURL = 'https://axios-app.firebaseio.com' // the prefix of the URL
axios.defaults.headers.get['Accept'] = 'application/json' // default header for all get request
axios.defaults.headers.post['Accept'] = 'application/json' // default header for all POST request
Then, in a component, we can use axios more succinctly, not needing to set those headers, but still having an opportunity to customize the final URL endpoint:
// form.js component
import axios from 'axios';
export default {
methods : {
onSubmit () {
// The URL is now https://axios-app.firebaseio.com/users.json
axios.post('/users.json', formData)
.then(res => console.log(res))
.catch(error => console.log(error))
}
}
}
Hinweis: Dieses Beispiel ist in Vue, aber das Konzept lässt sich auf jede JavaScript-Situation übertragen.
Benutzerdefinierte Instanz
Das Einrichten einer "benutzerdefinierten Instanz" ähnelt einer globalen Konfiguration, ist aber auf bestimmte Komponenten beschränkt. Es ist also immer noch eine DRY-Technik, aber mit Hierarchie.
Wir richten unsere benutzerdefinierte Instanz in einer neuen Datei ein (nennen wir sie authAxios.js) und importieren sie in die "betroffenen" Komponenten.
// authAxios.js
import axios from 'axios'
const customInstance = axios.create ({
baseURL : 'https://axios-app.firebaseio.com'
})
customInstance.defaults.headers.post['Accept'] = 'application/json'
// Or like this...
const customInstance = axios.create ({
baseURL : 'https://axios-app.firebaseio.com',
headers: {'Accept': 'application/json'}
})
Und dann importieren wir diese Datei in die Formular-Komponenten
// form.js component
// import from our custom instance
import axios from './authAxios'
export default {
methods : {
onSubmit () {
axios.post('/users.json', formData)
.then(res => console.log(res))
.catch(error => console.log(error))
}
}
}
Interceptors
Interceptors helfen in Fällen, in denen die globale Konfiguration oder die benutzerdefinierte Instanz zu allgemein ist, da sie, wenn Sie einen Header in ihren Objekten einrichten, für den Header jeder Anfrage innerhalb der betroffenen Komponenten gilt. Interceptors können beliebige Objekteigenschaften im laufenden Betrieb ändern. Wir können zum Beispiel einen anderen Header senden (auch wenn wir einen im Objekt eingestellt haben) basierend auf einer beliebigen Bedingung, die wir innerhalb des Interceptors wählen.
Interceptors können sich in der main.js-Datei oder einer benutzerdefinierten Instanzdatei befinden. Anfragen werden abgefangen, nachdem sie gesendet wurden, und ermöglichen es uns, die Behandlung der Antwort zu ändern.
// Add a request interceptor
axios.interceptors.request.use(function (config) {
// Do something before request is sent, like we're inserting a timeout for only requests with a particular baseURL
if (config.baseURL === 'https://axios-app.firebaseio.com/users.json') {
config.timeout = 4000
} else {
return config
}
console.log (config)
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
// Do something with response data like console.log, change header, or as we did here just added a conditional behaviour, to change the route or pop up an alert box, based on the reponse status
if (response.status === 200 || response.status 201) {
router.replace('homepage') }
else {
alert('Unusual behaviour')
}
console.log(response)
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
Interceptors fangen, wie der Name schon sagt, sowohl Anfragen als auch Antworten ab, um basierend auf den bereitgestellten Bedingungen unterschiedlich zu reagieren. Im obigen Anfrage-Interceptor haben wir zum Beispiel ein bedingtes Timeout eingefügt, nur wenn die Anfragen eine bestimmte baseURL haben. Für die Antwort können wir sie abfangen und modifizieren, was wir zurückbekommen, z. B. die Route ändern oder eine Alert-Box anzeigen, abhängig vom Statuscode. Wir können sogar mehrere Bedingungen basierend auf verschiedenen Fehlercodes angeben.
Interceptors werden sich als nützlich erweisen, wenn Ihr Projekt größer wird und Sie viele Routen und verschachtelte Routen haben, die alle basierend auf verschiedenen Auslösern mit Servern kommunizieren. Über die von mir oben genannten Bedingungen hinaus gibt es viele andere Situationen, die die Verwendung von Interceptors rechtfertigen können, basierend auf Ihrem Projekt.
Interessanterweise können wir einen Interceptor auswerfen, um zu verhindern, dass er überhaupt eine Wirkung hat. Wir müssen den Interceptor einer Variablen zuweisen und ihn mit der entsprechend benannten eject-Methode auswerfen.
const reqInterceptor = axios.interceptors.request.use(function (config) {
// Do something before request is sent, like we're inserting a timeout for only requests with a particular baseURL
if (config.baseURL === 'https://axios-app.firebaseio.com/users.json') {
config.timeout = 4000
} else {
return config
}
console.log (config)
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
const resInterceptor = axios.interceptors.response.use(function (response) {
// Do something with response data like console.log, change header, or as we did here just added a conditional behaviour, to change the route or pop up an alert box, based on the reponse status
if (response.status === 200 || response.status 201) {
router.replace('homepage')
} else {
alert('Unusual behaviour')
}
console.log(response)
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
axios.interceptors.request.eject(reqInterceptor);
axios.interceptors.request.eject(resInterceptor);
Obwohl es weniger gebräuchlich ist, ist es möglich, einen Interceptor in eine Bedingung zu setzen oder ihn basierend auf einem Ereignis zu entfernen.
Hoffentlich gibt Ihnen dies eine gute Vorstellung davon, wie axios funktioniert und wie es verwendet werden kann, um API-Anfragen in einer Anwendung DRY zu halten. Während wir die Oberfläche ankratzten, indem wir gängige Anwendungsfälle und Konfigurationen hervorheben, bietet axios viele weitere Vorteile, die Sie in der Dokumentation erkunden können, einschließlich der Möglichkeit, Anfragen abzubrechen und vor Cross-Site Request Forgery zu schützen, unter anderem weitere großartige Möglichkeiten.
Der richtige MIME-Typ für JSON ist
application/json, nicht eine Dateiendung.json, wie Sie sie hier haben.Zur Kenntnis genommen. Danke!
Warum eine weitere Abhängigkeit hinzufügen (was Wartungskosten verursacht und wir haben kürzlich gesehen, dass einige dieser Bibliotheken wie
requestveraltet sind und als veraltet gelten), wenn eine moderne, standardbasiertefetchAPI existiert und in Browsern integriert ist?Aus dem Beitrag
@Geoff Graham (kann nicht direkt antworten) Ich habe das nie wirklich verstanden
Ein Missverständnis einer Funktion bedeutet nicht, dass die Funktion "umständlich" ist. Es bedeutet, dass Ihr Verständnis umständlich ist. Ich wünschte, mehr Leute würden diesen Unterschied machen. Ich gehe hier davon aus, dass das Fehlen von Fehlern bei 404s usw. als positive Ergebnisse und nicht als Fehler von fetch, als "umständlich" bezeichnet wird.
Abgesehen davon sehe ich nichts in axios, was Sie nicht genauso einfach mit fetch machen können. (Mit der möglichen Ausnahme, wie axios in Node funktioniert, habe ich dort keine Erfahrung. Möglicherweise auch die Anforderungsstatus, wenn ich mich recht erinnere.)
Ich bin auf Adams Seite.
Außerdem konnte ich keinen der zitierten Artikel finden.
Hallo Martin! Ich nehme hier keine "Parteien". Der ursprüngliche Kommentar stellt eine Frage, die der Autor im Abschnitt "Installation und die Grundlagen" beantwortet hat. Schön zu hören, dass Sie eine Meinung dazu haben.
Es gibt ein
application.jsonanstelle vonapplication/json.Es ist ein Tippfehler. Er wurde korrigiert :)
Ich weiß von der globalen Konfiguration und Interceptors. Ich verwende Interceptors in meiner React-App mit Tokens, aber ich hatte Fälle, in denen ich unterschiedliche Tokens basierend auf der Architektur gesendet habe. Jetzt weiß ich, dass ich auswerfen oder (in Fällen, in denen ich eine andere BaseURL benötige) eine Instanz erstellen kann.
Guter Artikel. Danke.
Guter Artikel! Nur um den Lesern einige einschränkende Worte mit auf den Weg zu geben: Bitte überlegen Sie, ob axios die Standardwahl für Projekte sein sollte (ich habe viele Teams gesehen, die es zuerst wählen, anstatt das zu berücksichtigen, was sie tatsächlich brauchen).
Wenn Sie IE-Unterstützung benötigen, dann ist axios wahrscheinlich Ihre beste Wahl.
Wenn Sie eine verbesserte Ergonomie gegenüber der fetch API benötigen, würde ich jedoch empfehlen, eine benutzerdefinierte Wrapper-Funktion über
fetchzu verwenden oder kleine Bibliotheken wie wretch zu verwenden. Im Vergleich dazu ist axios ziemlich schwer.Was ist mit axios-Klassendienst mit mehreren URL-Servern?
Man könnte etwas wie das hier verwenden: https://www.npmjs.com/package/axios-multi-api, um 100 % DRY zu bleiben, wenn man Axios verwendet.
Haftungsausschluss: Ich bin der Autor des npm-Pakets und zufällig auf Ihrem Blog erschienen, daher dachte ich, ich teile es hier :)