Verwendung von XMLHttpRequest
Baseline Widely available *
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
* Some parts of this feature may have varying levels of support.
In diesem Leitfaden betrachten wir, wie Sie XMLHttpRequest
verwenden können, um HTTP-Anfragen zu stellen, um Daten zwischen der Website und einem Server auszutauschen.
Beispiele für gängige und weniger häufige Anwendungsfälle von XMLHttpRequest
sind enthalten.
Um eine HTTP-Anfrage zu senden:
- Erstellen Sie ein
XMLHttpRequest
-Objekt - Öffnen Sie eine URL
- Senden Sie die Anfrage.
Nachdem die Transaktion abgeschlossen ist, enthält das XMLHttpRequest
-Objekt nützliche Informationen wie den Antworttext und den HTTP-Status des Ergebnisses.
function reqListener() {
console.log(this.responseText);
}
const req = new XMLHttpRequest();
req.addEventListener("load", reqListener);
req.open("GET", "http://www.example.org/example.txt");
req.send();
Arten von Anfragen
Eine Anfrage, die über XMLHttpRequest
gesendet wird, kann die Daten auf zwei Arten abrufen: asynchron oder synchron. Die Art der Anfrage wird durch das optionale Argument async
(das dritte Argument) bestimmt, das in der Methode XMLHttpRequest.open()
gesetzt wird. Wenn dieses Argument true
ist oder nicht angegeben wurde, wird die XMLHttpRequest
-Anfrage asynchron verarbeitet, andernfalls wird der Vorgang synchron abgewickelt. Eine detaillierte Diskussion und Demonstrationen dieser beiden Anfragearten finden Sie auf der Seite synchronen und asynchronen Anfragen. Sie können keine synchronen Anfragen außerhalb von Web-Workern verwenden, da dies die Hauptoberfläche einfrieren würde.
Hinweis:
Der Konstruktor XMLHttpRequest
ist nicht nur auf XML-Dokumente beschränkt. Er beginnt mit "XML", da das ursprüngliche Format, das für asynchronen Datenaustausch verwendet wurde, XML war.
Umgang mit Antworten
Es gibt mehrere Arten von Antwortattributen, die für den XMLHttpRequest()
-Konstruktor definiert sind. Diese liefern dem XMLHttpRequest
-Client wichtige Informationen über den Status der Antwort. Einige Anwendungsfälle, bei denen mit Nicht-Text-Antworttypen gearbeitet wird, können Manipulation und Analyse erfordern und werden in den folgenden Abschnitten dargestellt.
Analyse und Manipulation der responseXML
-Eigenschaft
Wenn Sie XMLHttpRequest
verwenden, um den Inhalt eines entfernten XML-Dokuments zu erhalten, ist die responseXML
-Eigenschaft ein DOM-Objekt, das ein geparstes XML-Dokument enthält. Dies kann schwierig zu analysieren und zu manipulieren sein. Es gibt vier Hauptmethoden, um dieses XML-Dokument zu analysieren:
- Verwendung von XPath, um Teile davon zu adressieren (oder darauf zu verweisen).
- Manuelles Parsen und Serialisieren von XML als Zeichenfolgen oder Objekte.
- Verwendung von
XMLSerializer
, um DOM-Bäume in Zeichenfolgen oder Dateien zu serialisieren. RegExp
kann verwendet werden, wenn Sie den Inhalt des XML-Dokuments im Voraus kennen. Es könnte notwendig sein, Zeilenumbrüche zu entfernen, wenn SieRegExp
verwenden. Diese Methode sollte jedoch nur als "letzter Ausweg" betrachtet werden, da sie bei einer geringfügigen Änderung des XML-Codes wahrscheinlich fehlschlägt.
Hinweis: XMLHttpRequest
kann nun HTML für Sie interpretieren, indem die responseXML
-Eigenschaft genutzt wird. Lesen Sie den Artikel über HTML in XMLHttpRequest, um mehr darüber zu erfahren.
Verarbeitung der responseText
-Eigenschaft, die ein HTML-Dokument enthält
Wenn Sie XMLHttpRequest
verwenden, um den Inhalt einer entfernten HTML-Webseite zu erhalten, ist die responseText
-Eigenschaft eine Zeichenfolge, die das rohe HTML enthält. Dies könnte schwierig zu analysieren und zu manipulieren sein. Es gibt drei Hauptwege, dieses rohe HTML zu analysieren und zu verarbeiten:
- Verwenden Sie die
XMLHttpRequest.responseXML
-Eigenschaft, wie im Artikel HTML in XMLHttpRequest beschrieben. - Injizieren Sie den Inhalt in den Body eines Dokumentfragments über
fragment.body.innerHTML
und durchlaufen Sie den DOM des Fragments. RegExp
kann verwendet werden, wenn der Inhalt vonresponseText
im Voraus bekannt ist. Der Umgang mit Zeilenumbrüchen könnte notwendig sein. Allerdings ist dies eine Methode des „letzten Auswegs“, da sie bei Änderungen am HTML-Code wahrscheinlich fehlschlägt.
Umgang mit Binärdaten
Obwohl XMLHttpRequest
am häufigsten verwendet wird, um Textdaten zu senden und zu empfangen, kann es auch für den Umgang mit Binärdaten genutzt werden. Es gibt mehrere bewährte Methoden, um die Antwort einer XMLHttpRequest
zur Verarbeitung binärer Inhalte zu zwingen. Dazu gehört die Verwendung der Methode overrideMimeType()
am XMLHttpRequest
-Objekt, was eine funktionierende Lösung darstellt.
const req = new XMLHttpRequest();
req.open("GET", url);
// retrieve data unprocessed as a binary string
req.overrideMimeType("text/plain; charset=x-user-defined");
/* … */
Neue Techniken sind jedoch verfügbar, da das Attribut responseType
nun eine Anzahl zusätzlicher Inhaltstypen unterstützt, was das Senden und Empfangen binärer Daten einfacher macht.
Ein Beispiel dafür ist die Verwendung des responseType
mit "arraybuffer"
, um den entfernten Inhalt in ein ArrayBuffer
-Objekt zu laden, welches die rohen Binärdaten speichert.
const req = new XMLHttpRequest();
req.onload = (e) => {
const arraybuffer = req.response; // not responseText
/* … */
};
req.open("GET", url);
req.responseType = "arraybuffer";
req.send();
Weitere Beispiele finden Sie auf der Seite Senden und Empfangen von Binärdaten.
Überwachung des Fortschritts
XMLHttpRequest
ermöglicht es, Ereignisse zu überwachen, die während der Verarbeitung einer Anfrage auftreten können. Dazu gehören regelmäßige Fortschrittsbenachrichtigungen, Fehlermeldungen und dergleichen.
Die Unterstützung für DOM-progress
-Ereignisse bei der Überwachung von XMLHttpRequest
-Transfers folgt der Spezifikation für Fortschrittsereignisse: Diese Ereignisse implementieren die ProgressEvent
-Schnittstelle. Die tatsächlichen Ereignisse, die überwacht werden können, um den Status einer laufenden Übertragung zu bestimmen, sind:
progress
-
Die Menge der abgerufenen Daten hat sich geändert.
load
-
Die Übertragung ist abgeschlossen; alle Daten befinden sich jetzt in der Antwort.
const req = new XMLHttpRequest();
req.addEventListener("progress", updateProgress);
req.addEventListener("load", transferComplete);
req.addEventListener("error", transferFailed);
req.addEventListener("abort", transferCanceled);
req.open();
// …
// progress on transfers from the server to the client (downloads)
function updateProgress(event) {
if (event.lengthComputable) {
const percentComplete = (event.loaded / event.total) * 100;
// …
} else {
// Unable to compute progress information since the total size is unknown
}
}
function transferComplete(evt) {
console.log("The transfer is complete.");
}
function transferFailed(evt) {
console.log("An error occurred while transferring the file.");
}
function transferCanceled(evt) {
console.log("The transfer has been canceled by the user.");
}
Wir fügen Ereignis-Listener für die verschiedenen Ereignisse hinzu, die während einer Datenübertragung mit XMLHttpRequest
gesendet werden.
Hinweis:
Sie müssen die Ereignis-Listener hinzufügen, bevor Sie open()
auf der Anfrage aufrufen. Andernfalls werden keine progress
-Ereignisse ausgelöst.
Der Fortschrittsereignishandler, der durch die Funktion updateProgress()
in diesem Beispiel definiert wird, erhält die Gesamtanzahl der zu übertragenden Bytes sowie die bisher übertragenen Bytes in den Feldern total
und loaded
des Ereignisses. Wenn jedoch das Feld lengthComputable
falsch ist, ist die Gesamtlänge unbekannt und beträgt null.
Fortschrittsereignisse gibt es sowohl für Download- als auch für Upload-Übertragungen. Die Download-Ereignisse werden auf dem XMLHttpRequest
-Objekt selbst ausgelöst, wie im obigen Beispiel gezeigt. Die Upload-Ereignisse werden auf dem XMLHttpRequest.upload
-Objekt ausgelöst, wie unten gezeigt:
const req = new XMLHttpRequest();
req.upload.addEventListener("progress", updateProgress);
req.upload.addEventListener("load", transferComplete);
req.upload.addEventListener("error", transferFailed);
req.upload.addEventListener("abort", transferCanceled);
req.open();
Hinweis:
Fortschrittsereignisse sind nicht für das
file:
-Protokoll verfügbar.
Fortschrittsereignisse treten für jeden empfangenen Datenblock auf, einschließlich des letzten Blocks, falls der letzte Block empfangen und die Verbindung geschlossen wird, bevor das Fortschrittsereignis ausgelöst wird. In diesem Fall wird das Fortschrittsereignis automatisch ausgelöst, wenn das Ladevorgangsereignis für dieses Paket eintritt. So können Sie den Fortschritt zuverlässig überwachen, indem Sie nur das "progress"-Ereignis beobachten.
Man kann auch alle drei Zustände des Abschlusses (abort
, load
oder error
) mithilfe des loadend
-Ereignisses erkennen:
req.addEventListener("loadend", loadEnd);
function loadEnd(e) {
console.log(
"The transfer finished (although we don't know if it succeeded or not).",
);
}
Beachten Sie, dass es keine Möglichkeit gibt, aus den Informationen, die durch das loadend
-Ereignis empfangen werden, sicher festzustellen, welcher Zustand den Vorgang beendet hat; Sie können dies jedoch verwenden, um Aufgaben zu behandeln, die in allen Abschluss-Szenarien ausgeführt werden müssen.
Abrufen des Zuletzt-Geändert-Datums
function getHeaderTime() {
console.log(this.getResponseHeader("Last-Modified")); // A valid GMTString date or null
}
const req = new XMLHttpRequest();
req.open(
"HEAD", // use HEAD when you only need the headers
"your-page.html",
);
req.onload = getHeaderTime;
req.send();
Etwas tun, wenn sich das Zuletzt-Geändert-Datum ändert
Lassen Sie uns zwei Funktionen erstellen:
function getHeaderTime() {
const lastVisit = parseFloat(
window.localStorage.getItem(`lm_${this.filepath}`),
);
const lastModified = Date.parse(this.getResponseHeader("Last-Modified"));
if (isNaN(lastVisit) || lastModified > lastVisit) {
window.localStorage.setItem(`lm_${this.filepath}`, Date.now());
isFinite(lastVisit) && this.callback(lastModified, lastVisit);
}
}
function ifHasChanged(URL, callback) {
const req = new XMLHttpRequest();
req.open("HEAD" /* use HEAD - we only need the headers! */, URL);
req.callback = callback;
req.filepath = URL;
req.onload = getHeaderTime;
req.send();
}
Und testen:
// Let's test the file "your-page.html"
ifHasChanged("your-page.html", function (modified, visit) {
console.log(
`The page '${this.filepath}' has been changed on ${new Date(
nModified,
).toLocaleString()}!`,
);
});
Wenn Sie wissen möchten, ob sich die aktuelle Seite geändert hat, lesen Sie den Artikel über document.lastModified
.
Cross-Site-XMLHttpRequest
Moderne Browser unterstützen Cross-Site-Anfragen durch Implementierung des Cross-Origin Resource Sharing (CORS)-Standards. Solange der Server so konfiguriert ist, dass er Anfragen aus dem Ursprung Ihrer Webanwendung erlaubt, wird XMLHttpRequest
funktionieren. Andernfalls wird eine INVALID_ACCESS_ERR
-Ausnahme ausgelöst.
Umgehen des Caches
Eine browserübergreifende Möglichkeit, den Cache zu umgehen, besteht darin, einen Zeitstempel an die URL anzuhängen und sicherzustellen, dass ein „?“ oder „&“ wie erforderlich eingeschlossen wird. Zum Beispiel:
http://example.com/bar.html -> http://example.com/bar.html?12345 http://example.com/bar.html?foobar=baz -> http://example.com/bar.html?foobar=baz&12345
Da der lokale Cache nach URL indiziert wird, führt dies dazu, dass jede Anfrage einzigartig ist, wodurch der Cache umgangen wird.
Sie können URLs automatisch anpassen, indem Sie den folgenden Code verwenden:
const req = new XMLHttpRequest();
req.open("GET", url + (/\?/.test(url) ? "&" : "?") + new Date().getTime());
req.send(null);
Sicherheit
Die empfohlene Methode zur Aktivierung von Cross-Site-Scripting ist die Verwendung des HTTP-Headers Access-Control-Allow-Origin
in der Antwort auf die XMLHttpRequest.
XMLHttpRequests werden gestoppt
Wenn Sie feststellen, dass eine XMLHttpRequest status=0
und statusText=null
erhält, bedeutet dies, dass die Anfrage nicht ausgeführt werden durfte. Sie war UNSENT
. Ein wahrscheinlicher Grund hierfür ist, dass sich der XMLHttpRequest
-Ursprung (zum Zeitpunkt der Erstellung des XMLHttpRequest) geändert hat, als die XMLHttpRequest anschließend open()
wurde. Dieser Fall kann beispielsweise auftreten, wenn eine XMLHttpRequest ausgelöst wird, während ein Fenster geschlossen wird. Der effektivste Weg, dieses Problem zu vermeiden, besteht darin, einen Listener für das DOMActivate
-Ereignis des neuen Fensters zu setzen, das ausgelöst wird, sobald das unload
-Ereignis des geschlossenen Fensters ausgelöst wurde.
Spezifikationen
Specification |
---|
XMLHttpRequest # interface-xmlhttprequest |
Browser-Kompatibilität
Report problems with this compatibility data on GitHubdesktop | mobile | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
XMLHttpRequest | ||||||||||||
XMLHttpRequest() constructor | ||||||||||||
abort | ||||||||||||
abort event | ||||||||||||
Authorization header removed from cross-origin redirects | ||||||||||||
error event | ||||||||||||
getAllResponseHeaders | ||||||||||||
Header names returned in all lower case | ||||||||||||
getResponseHeader | ||||||||||||
load event | ||||||||||||
loadend event | ||||||||||||
loadstart event | ||||||||||||
open | ||||||||||||
overrideMimeType | ||||||||||||
progress event | ||||||||||||
readyState | ||||||||||||
readystatechange event | ||||||||||||
response | ||||||||||||
responseText | ||||||||||||
responseType | ||||||||||||
responseType.arraybuffer_value | ||||||||||||
responseType.blob_value | ||||||||||||
responseType.document_value | ||||||||||||
responseType.json_value | ||||||||||||
responseURL | ||||||||||||
responseXML | ||||||||||||
send | ||||||||||||
ArrayBufferView as parameter to send() | ||||||||||||
ArrayBuffer as parameter to send() | ||||||||||||
Blob as parameter to send() | ||||||||||||
FormData as parameter to send() | ||||||||||||
URLSearchParams as parameter to send() | ||||||||||||
setAttributionReporting | ||||||||||||
setPrivateToken | ||||||||||||
setRequestHeader | ||||||||||||
status | ||||||||||||
statusText | ||||||||||||
timeout | ||||||||||||
timeout event | ||||||||||||
upload | ||||||||||||
withCredentials | ||||||||||||
Available in workers |
Legend
Tip: you can click/tap on a cell for more information.
- Full support
- Full support
- Partial support
- Partial support
- No support
- No support
- Experimental. Expect behavior to change in the future.
- See implementation notes.
- Has more compatibility info.