1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
|
---
title: Erste Schritte
slug: Web/Guide/AJAX/Getting_Started
tags:
- AJAX
- API
- JavaScript
- XMLHttRequest
translation_of: Web/Guide/AJAX/Getting_Started
original_slug: Web/Guide/AJAX/Erste_Schritte
---
<div>{{DefaultAPISidebar("XMLHttpRequest")}}</div>
<p class="summary">Dieser Artikel führt Sie durch die AJAX-Grundlagen und gibt einige einfache praktische Beispiele für den Einstieg.</p>
<h2 id="Was_ist_AJAX">Was ist AJAX?</h2>
<p>AJAX steht für <strong>A</strong>synchronous <strong>J</strong>avaScript <strong>A</strong>nd <strong>X</strong>ML. Kurz gesagt ist es die Verwendung des XMLHttpRequest-Objekts zur Kommunikation mit Servern. Es kann Informationen in verschiedenen Formaten senden und empfangen, darunter JSON, XML, HTML und Textdateien. Das ansprechendste Merkmal von AJAX ist seine "asynchrone" Natur, d.h. es kann mit dem Server kommunizieren, Daten austauschen und die Seite aktualisieren, ohne die Seite aktualisieren zu müssen.</p>
<p>Die zwei Hauptmerkmale von AJAX ermöglichen Folgendes::</p>
<ul>
<li>Anfragen an den Server stellen, ohne die Seite neu zu laden</li>
<li>Daten vom Server empfangen und mit ihnen arbeiten</li>
</ul>
<h2 id="Schritt_1_–_Wie_man_eine_HTTP-Anfrage_stellt">Schritt 1 – Wie man eine HTTP-Anfrage stellt</h2>
<p>Um mit JavaScript eine HTTP-Anfrage an den Server zu stellen, wird eine Instanz eines Objekts mit der notwendigen Funktionalität benötigt. An dieser Stelle kommt XMLHttpRequest ins Spiel. Sein Vorgänger entstand im Internet Explorer als ein ActiveX-Objekt namens XMLHTTP. Dann folgten Mozilla, Safari und andere Browser, die ein XMLHttpRequest-Objekt implementierten, das die Methoden und Eigenschaften des ursprünglichen ActiveX-Objekts von Microsoft unterstützte. In der Zwischenzeit implementierte Microsoft auch XMLHttpRequest.</p>
<pre class="brush: js notranslate">// Old compatibility code, no longer needed.
if (window.XMLHttpRequest) { // Mozilla, Safari, IE7+ ...
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE 6 and older
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
</pre>
<div class="note">Hinweis: Zur Veranschaulichung ist die obige Abbildung eine etwas vereinfachte Version des Codes, der für die Erstellung einer XMLHttp-Instanz zu verwenden ist. Ein realistischeres Beispiel finden Sie in Schritt 3 dieses Artikels.</div>
<p>Nachdem die Anfrage abgesandt wurde, kommt eine Antwort zurück. Jetzt muss dem XMLHttp-Anfrageobjekt mitteilt werden, welche JavaScript-Funktion die Antwort behandeln wird, indem die <code>onreadystatechange</code> -Eigenschaft des Objekts gesetzt und nach der Funktion benannt wird, die aufgerufen werden soll, wenn sich der Status der Anfrage ändert, etwa so:</p>
<pre class="brush: js notranslate"><code>httpRequest.onreadystatechange = nameOfTheFunction;</code></pre>
<p>Beachten Sie, dass hinter dem Funktionsnamen keine Klammern oder Parameter stehen, da Sie der Funktion eine Referenz zuweisen, anstatt sie tatsächlich aufzurufen. Anstatt einen Funktionsnamen anzugeben, können Sie alternativ auch die JavaScript-Technik verwenden, Funktionen on the fly zu definieren (so genannte "anonyme Funktionen"), um die Aktionen zu definieren, die die Antwort verarbeiten, wie z.B:</p>
<pre class="brush: js notranslate">httpRequest.onreadystatechange = function(){
// Process the server response here.
};
</pre>
<p>Nachdem Sie erklärt haben, was passiert, wenn Sie die Antwort erhalten, müssen Sie als Nächstes die Anfrage tatsächlich stellen, indem Sie die open()- und send()-Methoden des HTTP-Anfrageobjekts aufrufen, und zwar wie folgt::</p>
<pre class="brush: js notranslate">httpRequest.open('GET', 'http://www.example.org/some.file', true);
httpRequest.send();
</pre>
<ul>
<li>
<p>Der erste Parameter des Aufrufs von open() ist die HTTP-Anforderungsmethode - GET, POST, HEAD oder eine andere von Ihrem Server unterstützte Methode. Behalten Sie die Methode in Großbuchstaben gemäß dem HTTP-Standard bei, da sonst einige Browser (wie Firefox) die Anfrage möglicherweise nicht verarbeiten. Weitere Informationen zu den möglichen HTTP-Anforderungsmethoden finden Sie in den <a class="external" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html">W3C specs</a>.</p>
</li>
<li>Der zweite Parameter ist die URL, an die Sie die Anfrage senden. Als Sicherheitsfunktion können Sie standardmäßig keine URLs auf 3rd-Party-Domains aufrufen. Stellen Sie sicher, dass Sie den genauen Domainnamen auf allen Ihren Seiten verwenden, sonst erhalten Sie beim Aufruf von <code>open()</code> einen "permission denied"-Fehler. Ein häufiger Fallstrick ist der Zugriff auf Ihre Website über <code>domain.tld</code>, aber der Versuch, Seiten mit www.domain.tld aufzurufen. Wenn Sie wirklich eine Anfrage an eine andere Domain senden müssen, siehe <a href="/en-US/docs/Web/HTTP/CORS">HTTP access control (CORS)</a>.</li>
<li>Der optionale dritte Parameter legt fest, ob die Anforderung asynchron ist. Wenn dies der <code>true</code> ist (Standardeinstellung), wird die JavaScript-Ausführung fortgesetzt, und der Benutzer kann mit der Seite interagieren, solange die Serverantwort noch nicht eingetroffen ist. Dies ist das erste A in AJAX.</li>
</ul>
<p>Der Parameter der send()-Methode kann jede Form von Daten beinhalten, die Sie beim <code>POST</code>-ing der Anfrage an den Server senden möchten. Formulardaten sollten in einem Format gesendet werden, das der Server parsen kann, wie ein Abfrage-String:</p>
<pre class="notranslate"><code>"name=value&anothername="+encodeURIComponent(myVar)+"&so=on"</code></pre>
<p>oder andere Formate wie <code>multipart/form-data</code>, JSON, XML, etc.</p>
<p>Beachten Sie, dass Sie möglicherweise den MIME-Typ der Anforderung angeben müssen, wenn Sie Daten <code>POST</code>-en wollen. Verwenden Sie beispielsweise Folgendes, bevor Sie <code>send()</code> für Formulardaten aufrufen, die als Abfragezeichenfolge gesendet werden::</p>
<pre class="brush: js notranslate">httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
</pre>
<h2 id="Schritt_2_-_Behandlung_der_Server-Antwort">Schritt 2 - Behandlung der Server-Antwort</h2>
<p>Als Sie die Anfrage abgeschickt haben, haben Sie den Namen einer JavaScript-Funktion zur Behandlung der Antwort angegeben:</p>
<pre class="brush: js notranslate">httpRequest.onreadystatechange = nameOfTheFunction;
</pre>
<p>Was soll diese Funktion tun? Zunächst muss die Funktion den Status der Anfrage überprüfen. Wenn der Status den Wert <code>XMLHttpRequest.DONE</code> (entsprechend 4) hat, bedeutet dies, dass die vollständige Serverantwort empfangen wurde und Sie mit der Verarbeitung fortfahren können.</p>
<pre class="brush: js notranslate">if (httpRequest.readyState === XMLHttpRequest.DONE) {
// Everything is good, the response was received.
} else {
// Not ready yet.
}
</pre>
<p>Die vollständige Liste <code>readyState</code> -Werte ist unter <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState">XMLHTTPRequest.readyState</a> dokumentiert und lautet wie folgt:</p>
<ul>
<li>0 (uninitialized) or (<strong>request not initialized</strong>)</li>
<li>1 (loading) or (<strong>server connection established</strong>)</li>
<li>2 (loaded) or (<strong>request received</strong>)</li>
<li>3 (interactive) or (<strong>processing request</strong>)</li>
<li>4 (complete) or (<strong>request finished and response is ready</strong>)</li>
</ul>
<p>Überprüfen Sie als Nächstes die <a href="/en-US/docs/Web/HTTP/Status">HTTP response status codes</a> der HTTP-Antwort. Die möglichen Codes sind beim <a class="external" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">W3C</a> aufgelistet. Im folgenden Beispiel unterscheiden wir zwischen einem erfolgreichen und einem nicht erfolgreichen AJAX-Aufruf, indem wir nach einem <code>200 OK</code>-Antwort-Code suchen.</p>
<pre class="brush: js notranslate">if (httpRequest.status === 200) {
// Perfect!
} else {
// There was a problem with the request.
// For example, the response may have a 404 (Not Found)
// or 500 (Internal Server Error) response code.
}
</pre>
<p>Nachdem Sie den Status der Anfrage und den HTTP-Statuscode der Antwort überprüft haben, können Sie mit den vom Server gesendeten Daten tun, was Sie wollen. Sie haben zwei Möglichkeiten, auf diese Daten zuzugreifen:</p>
<ul>
<li><code>httpRequest.responseText</code> – gibt die Server-Antwort als eine Zeichenkette aus Text zurück</li>
<li><code>httpRequest.responseXML</code> – gibt die Antwort als ein XMLDocument-Objekt zurück, das Sie mit JavaScript-DOM-Funktionen durchlaufen können</li>
</ul>
<p>Beachten Sie, dass die obigen Schritte nur gültig sind, wenn Sie eine asynchrone Anforderung verwendet haben (der dritte Parameter von <code>open()</code> war nicht spezifiziert oder auf true gesetzt). Wenn Sie eine synchrone Anforderung verwendet haben, brauchen Sie keine Funktion anzugeben, aber davon wird dringend abgeraten, da dies eine schlechte Benutzerführung zur Folge hat.</p>
<h2 id="Schritt_3_–_Ein_einfaches_Beispiel">Schritt 3 – Ein einfaches Beispiel</h2>
<p>Lassen Sie uns das alles mit einer einfachen HTTP-Anfrage zusammenfassen. Unser JavaScript wird ein HTML-Dokument, <code>test.html</code>, anfordern, das den Text "Ich bin ein Test" enthält. Dann <code>alert()</code> wir den Inhalt der Antwort. Beachten Sie, dass dieses Beispiel <a href="https://wiki.selfhtml.org/wiki/Vanilla-JS">Vanilla JavaScript</a> verwendet - es handelt sich nicht um jQuery. Außerdem sollten sich die HTML-, XML- und PHP-Dateien im selben Verzeichnis befinden.</p>
<pre class="brush: html notranslate"><button id="ajaxButton" type="button">Make a request</button>
<script>
(function() {
var httpRequest;
document.getElementById("ajaxButton").addEventListener('click', makeRequest);
function makeRequest() {
httpRequest = new XMLHttpRequest();
if (!httpRequest) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
httpRequest.onreadystatechange = alertContents;
httpRequest.open('GET', 'test.html');
httpRequest.send();
}
function alertContents() {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
alert(httpRequest.responseText);
} else {
alert('There was a problem with the request.');
}
}
}
})();
</script>
</pre>
<p>In this example:</p>
<ul>
<li>Der Benutzer klickt auf den "Make a request"- Button;</li>
<li>Der Ereignisbehandler ruft die <code>makeRequest()-</code>Funktion auf;</li>
<li>Die Anfrage wird gestellt und dann (<code>onreadystatechange</code>) zur Ausführung an <code>alertContents()</code> übergeben;</li>
<li><code>alertContents()</code> prüft, ob die Antwort empfangen wurde und OK ist, dann <code>alert()</code> den Inhalt der <code>test.html</code>-Datei.</li>
</ul>
<div class="note">Hinweis: Wenn Sie eine Anfrage an ein Stück Code senden, das XML statt einer statischen HTML-Datei zurückgibt, müssen Sie die Antwortheader so einstellen, dass sie im Internet Explorer funktionieren.. Wenn Sie den Header Content-Type <code>Content-Type: application/xml nicht angeben</code>, gibt IE nach der Zeile, in der Sie versucht haben, auf ein XML-Element zuzugreifen, einen JavaScript-Fehler " Object Expected " aus.</div>
<div class="note"><strong>Hinweis 2</strong>: Wenn Sie den Header <code>Cache-Control: no-cache</code> nicht setzen, wird der Browser die Antwort zwischenspeichern und die Anfrage nie erneut senden, was das Debugging erschwert. Sie können auch einen immer unterschiedlichen GET-Parameter hinzufügen, wie einen Zeitstempel oder eine Zufallszahl (siehe <a href="/en/DOM/XMLHttpRequest/Using_XMLHttpRequest#Bypassing_the_cache">bypassing the cache</a>)</div>
<div class="note"><strong>Hinweis 3</strong>: Wenn die <code>httpRequest</code>-Variable global verwendet wird, können sich konkurrierende Aufrufe von <code>makeRequest()</code> gegenseitig überschreiben und eine Wettlaufsituation auslösen. Wird der <code>httpRequest </code>lokal ain einer <a href="/en/JavaScript/Guide/Closures">closure</a> Umgebung mit einer AJAX-Function deklariert, so wird dies vermieden.</div>
<p>Im Falle eines Kommunikationsfehlers (z. B. bei einem Serverausfall) wird beim Zugriff auf den Antwortstatus in der Methode <code>onreadystatechange</code> eine Ausnahmemeldung zurückgegeben. Um dieses Problem zu beheben, könnten Sie Ihre <code>if...then</code>-Anweisung in a <code>try...catch</code> packen:</p>
<pre class="brush: js notranslate">function alertContents() {
try {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
alert(httpRequest.responseText);
} else {
alert('There was a problem with the request.');
}
}
}
catch( e ) {
alert('Caught Exception: ' + e.description);
}
}
</pre>
<h2 id="Schritt_4_–_Arbeiten_mit_der_XML-Antwort">Schritt 4 – Arbeiten mit der XML-Antwort</h2>
<p>Im vorherigen Beispiel haben wir nach dem Empfang der Antwort auf die HTTP-Anforderung die Eigenschaft <code>responseText</code> des Anforderungsobjekts verwendet, die den Inhalt der Datei <code>test.html</code> enthielt. Lassen Sie uns nun die <code>responseXML</code>-Eigenschaft ausprobieren.</p>
<p>Lassen Sie uns zunächst ein gültiges XML-Dokument erstellen, das wir später anfordern werden. Das Dokument (<code>test.xml</code>) enthält Folgendes:</p>
<pre class="brush: html notranslate"><?xml version="1.0" ?>
<root>
I'm a test.
</root>
</pre>
<p>Im Skript brauchen wir nur die Anforderungszeile zu ändern:</p>
<pre class="brush: html notranslate">...
onclick="makeRequest('test.xml')">
...
</pre>
<p>In <code>alertContents()</code> müssen wir die Zeile <code>alert(httpRequest.responseText);</code>ersetzen mit:</p>
<pre class="brush: js notranslate">var xmldoc = httpRequest.responseXML;
var root_node = xmldoc.getElementsByTagName('root').item(0);
alert(root_node.firstChild.data);
</pre>
<p>Dieser Code nimmt das von <code>responseXML</code> übergebene <code>XMLDocument</code>-Objekt und verwendet DOM-Methoden, um auf einige der im XML-Dokument enthaltenen Daten zuzugreifen. Sie können <a class="external" href="http://www.w3clubs.com/mozdev/test.xml">here</a> das <code>test.xml</code> and<a class="external" href="http://www.w3clubs.com/mozdev/httprequest_test_xml.html"> here</a> das aktualisierte test script aufrufen.</p>
<h2 id="Schritt_5_–_Arbeiten_mit_Daten">Schritt 5 – Arbeiten mit Daten</h2>
<p>Zum Schluss senden wir einige Daten an den Server und erhalten eine Antwort. Unser JavaScript wird diesmal eine dynamische Seite <code>test.php</code> anfordern, die die von uns gesendeten Daten entgegennimmt und einen "computed" string - "Hello, [user data]!" - den wir <code>alert()</code>-en werden.</p>
<p>Zuerst fügen wir unserem HTML ein Textfeld hinzu, damit der Benutzer seinen Namen eingeben kann:</p>
<pre class="brush: html notranslate"><label>Your name:
<input type="text" id="ajaxTextbox" />
</label>
<span id="ajaxButton" style="cursor: pointer; text-decoration: underline">
Make a request
</span></pre>
<p>Wir fügen auch eine Zeile zu unserem Event-Handler hinzu, um die Daten des Benutzers aus dem Textfeld zu holen und sie zusammen mit der URL unseres serverseitigen Skripts an die Funktion <code>makeRequest()</code> zu senden:</p>
<pre class="brush: js notranslate"> document.getElementById("ajaxButton").onclick = function() {
var userName = document.getElementById("ajaxTextbox").value;
makeRequest('test.php',userName);
};
</pre>
<p>Wir müssen <code>makeRequest()</code> so modifizieren, dass es die Benutzerdaten akzeptiert und an den Server weiterleitet. Wir werden die Anfragemethode von <code>GET</code> auf <code>POST</code> ändern und unsere Daten als Parameter in den Aufruf von <code>httpRequest.send()</code> aufnehmen:</p>
<pre class="brush: js notranslate"> function makeRequest(url, userName) {
...
httpRequest.onreadystatechange = alertContents;
httpRequest.open('POST', url);
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
httpRequest.send('userName=' + encodeURIComponent(userName));
}
</pre>
<p>Die Funktion <code>alertContents()</code> kann auf die gleiche Weise wie in Schritt 3 geschrieben werden, um unsere Zeichenfolge zu <code>alert()</code>-en, wenn das alles ist, was der Server zurückgibt.. Nehmen wir jedoch an, der Server wird sowohl die berechnete Zeichenkette als auch die ursprünglichen Benutzerdaten zurückgeben. Wenn also unser Benutzer "Jane" in das Textfeld eingibt, würde die Antwort des Servers wie folgt aussehen::</p>
<p><code>{"userData":"Jane","computedString":"Hi, Jane!"}</code></p>
<p>Um diese Daten mit <code>alertContents()</code> zu nutzen, können wir nicht einfach den <code>responseText</code> ausgeben, sondern wir müssen ihn parsen und die gewünschte Eigenschaft <code>computedString</code> <code>alert()</code>-en:</p>
<pre class="brush: js notranslate">function alertContents() {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
var response = JSON.parse(httpRequest.responseText);
alert(response.computedString);
} else {
alert('There was a problem with the request.');
}
}
}</pre>
<p>Die <code>test.php</code>-Datei sollte folgendes enthalten:</p>
<pre class="brush: php notranslate"><code>$name = (isset($_POST['userName'])) ? $_POST['userName'] : 'no name';
$computedString = "Hi, " . $name . "!";
$array = ['userName' => $name, 'computedString' => $computedString];
echo json_encode($array);</code></pre>
<p>Weitere Informationen zu DOM-Methoden finden Sie unter <a href="/en-US/docs/Web/API/Document_Object_Model">Document Object Model (DOM)</a>.</p>
<h2 id="Einfaches_zeitgesteuertes_XHR-Beispiel">Einfaches zeitgesteuertes XHR-Beispiel</h2>
<p>Es folgt ein weiteres einfaches Beispiel - hier laden wir eine Textdatei über XHR, deren Struktur wie folgt angenommen wird:</p>
<pre class="notranslate">TIME: 312.05
TIME: 312.07
TIME: 312.10
TIME: 312.12
TIME: 312.14
TIME: 312.15</pre>
<p>Sobald die Textdatei geladen ist, <code>split()</code>-en wir die Elemente an jedem Zeilenumbruchszeichen (<code>\n</code> - im Grunde genommen dort, wo jeder Zeilenumbruch in der Textdatei steht) in ein Array auf und geben dann die vollständige Liste der Zeitstempel und den letzten Zeitstempel auf der Seite aus.</p>
<p>Dies wird alle 5 Sekunden wiederholt, unter Verwendung eines <code>setInterval()</code> Aufrufs. Die Idee wäre, dass eine Art serverseitiges Skript die Textdatei kontinuierlich mit neuen Zeitstempeln aktualisiert, und unser XHR-Code verwendet wird, um den neuesten Zeitstempel auf der Client-Seite zu melden.</p>
<pre class="brush: html notranslate"><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>XHR log time</title>
<style>
</style>
</head>
<body>
<p id="writeData" class="data">Off-Line</p>
<p id="lastStamp">No Data yet</p>
<script>
const fullData = document.getElementById('writeData');
const lastData = document.getElementById('lastStamp');
function fetchData() {
console.log('Fetching updated data.');
let xhr = new XMLHttpRequest();
xhr.open("GET", "time-log.txt", true);
xhr.onload = function() {
updateDisplay(xhr.response);
}
xhr.send();
}
function updateDisplay(text) {
fullData.textContent = text;
let timeArray = text.split('\n');
// included because some file systems always include a blank line at the end of text files.
if(timeArray[timeArray.length-1] === '') {
timeArray.pop();
}
lastData.textContent = timeArray[timeArray.length-1];
}
setInterval(fetchData, 5000);
</script>
</body>
</html></pre>
|