Webtechnologien
Wintersemester 2024
Ajax
♯
♫
Ajax
<section id="ajax" class="slide cover"><div><h2>Ajax</h2> <footer> <ul> <li>1998 <q>Remote-Scripting-Komponente</q> im IE für <q>Outlook Web Access</q></li> <li>2005 Der Begriff AJAX wurde von Jesse James Garret in seinem Artikel <q>Ajax: A New Approach to Web Applications</q> bekannt gemacht</li> <li> <table> <tbody> <tr> <td>2005: Google ( Groups</td> <td>Maps</td> <td>Suggest</td> <td>Mail</td> <td>Finance )</td> </tr> </tbody> </table> </li> </ul> </footer> </div></section> <section class="slide" id="asynchronous-javascript-and-xml"><div><h2>Asynchronous JavaScript and XML</h2> <p><img src="Ajax-vergleich.svg" alt="Klassiches Model / Ajax" class="right" /></p> <ul> <li>Konzept der asynchronen Datenübertragung zwischen Browser und Server</li> <li>Ermöglicht es, aus einer bereits geladenen HTML-Seite HTTP-Anfragen duchzuführen und die Seite zu verändern, ohne sie komplett neu zu laden</li> </ul> <footer> <ul> <li>Sonst: Request-Response-Paradigma</li> <li>Ajax ist ein Verfahren Teile von angezeigten Web-Seiten direkt zu ersetzen, statt die ganze Seite neu zu laden.</li> <li>Blockiert nicht: Benutzer kann während der Calls weiter arbeiten</li> <li>Erfolgt meist über das nicht standardisierte XMLHttpRequest-Objekt</li> </ul> </footer> </div></section> <section class="slide" id="vor---nachteile"><div><h2>Vor- / Nachteile</h2> <div class="parts "> <div class="part"> <h3 id="vorteile">Vorteile</h3> <ul> <li>Kein Neuladen aufgebauter Seiten</li> <li>Geschwindigkeit</li> <li>Entlastung der Server / Netze</li> <li>Kein Browser-Plugin nötig</li> </ul> </div><div class="part"> <h3 id="nachteile">Nachteile</h3> <ul> <li>Umfangreiche Tests erforderlich</li> <li><q>Zurück</q>-Button *</li> <li>Bookmarks / Suchmaschinen *</li> <li>Polling nötig *</li> <li>Custom Lade-Feedback nötig</li> <li>Barrierefreiheit (Kein JS, kein Content)</li> </ul> <p><em>* früher, heute nicht mehr</em></p> </div> </div> </div></section> <section class="slide" id="anwendung"><div><h2>Anwendung</h2> <pre class="highlight language-js" data-lang="js"><code><span class="kd">const</span> <span class="nx">states</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">nicht init.</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">lade</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">geladen</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">interaktiv</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">fertig</span><span class="dl">'</span><span class="p">];</span> <span class="kd">const</span> <span class="nx">http_request</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">XMLHttpRequest</span><span class="p">();</span> <span class="nx">http_request</span><span class="p">.</span><span class="nx">onreadystatechange</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span> <span class="nf">alert</span><span class="p">(</span><span class="nx">states</span><span class="p">[</span><span class="nx">http_request</span><span class="p">.</span><span class="nx">readyState</span><span class="p">]);</span> <span class="p">};</span> <span class="nx">http_request</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">http://domain.de/folder/file.php</span><span class="dl">'</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span> <span class="nx">http_request</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span> <span class="c1">// auch wichtig</span> <span class="nx">http_request</span><span class="p">.</span><span class="nx">responseText</span> <span class="c1">// Antwort des Servers als Textstring</span> <span class="nx">http_request</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">==</span> <span class="mi">4</span> <span class="c1">// fertig</span> <span class="nx">http_request</span><span class="p">.</span><span class="nx">status</span> <span class="o">==</span> <span class="mi">200</span> <span class="c1">// alles ok</span> </code></pre> <p class="note right">Quelle: <a href="https://developer.mozilla.org/de/docs/AJAX/Einf%C3%BChrung">AJAX-Einführung</a></p> <footer> <ul> <li>HTML</li> <li>DOM zur Repräsentation der Daten</li> <li>JavaScript zur Manipulation des DOM</li> <li>XMLHttpRequest-Objekt als Bestandteil des Browsers, um Daten asynchroner mit dem Webserver austauschen zu können</li> </ul> <h3 id="verwendung">Verwendung</h3> <ul> <li>Instanz der benötigten Klasse erzeugen (nicht als globale Variable, da sich Request sonst überschreiben)</li> <li>dem HTTP Request-Objekt mitteilen, welche JavaScript-Funktion die Antwort abarbeiten soll</li> <li>Der zweite Parameter ist die URL der angeforderten Seite. Aus Sicherheitsgründen können keine Seiten auf 3rd-party Domains angefordert werden. Es muss sichergestellt werden, dass der exakte Domainname auf allen Seiten benutzt wird; andernfalls bekommt man einen ‘permission denied’-Fehler beim Aufruf von <code class="language-plaintext highlighter-rouge">open()</code>. Ein beliebter Fallstrick ist der Aufruf einer Seite mittels ‘domain.tld’, wobei die gewünschte Seite jedoch ‘www.domain.tld’ lautet.</li> <li>Der dritte Parameter gibt an, ob der Request asynchron sein soll (default). Wenn er auf true gesetzt ist, wird die JavaScript-Funktion weiter ausgeführt, während die Antwort des Servers noch aussteht. Das ist das A in AJAX.</li> <li><code class="language-plaintext highlighter-rouge">send()</code> bekommt als Parameter den Body, an den Server geschickt wird. Kann alles mögliche sein.</li> <li><code class="language-plaintext highlighter-rouge">READYSTATE_UNINITIALIZED (0)</code>: The object has been created, but not initialized (the open method has not been called).</li> <li><code class="language-plaintext highlighter-rouge">READYSTATE_LOADING (1)</code>: A request has been opened, but the send method has not been called.</li> <li><code class="language-plaintext highlighter-rouge">READYSTATE_LOADED (2)</code>: The send method has been called. No data is available yet.</li> <li><code class="language-plaintext highlighter-rouge">READYSTATE_INTERACTIVE (3)</code>: Some data has been received; however, responseText is not available.</li> <li><code class="language-plaintext highlighter-rouge">READYSTATE_COMPLETE (4)</code>: All the data has been received.</li> </ul> </footer> </div></section> <section class="slide" id="anwendung-1"><div><h2>Anwendung</h2> <pre class="highlight language-js" data-lang="js"><code><span class="nx">httpRequest</span><span class="p">.</span><span class="nx">onreadystatechange</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span> <span class="nf">alert</span><span class="p">(</span><span class="dl">"</span><span class="s2">:-)</span><span class="dl">"</span><span class="p">);</span> <span class="p">};</span> <span class="nx">httpRequest</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST</span><span class="dl">'</span><span class="p">,</span> <span class="nx">url</span><span class="p">);</span> <span class="nx">httpRequest</span><span class="p">.</span><span class="nf">setRequestHeader</span><span class="p">(</span><span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">application/x-www-form-urlencoded</span><span class="dl">'</span><span class="p">);</span> <span class="nx">httpRequest</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="dl">'</span><span class="s1">userName=</span><span class="dl">'</span> <span class="o">+</span> <span class="nf">encodeURIComponent</span><span class="p">(</span><span class="nx">userName</span><span class="p">));</span> <span class="c1">// andere Funktionen</span> <span class="nx">httpRequest</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="nx">method</span><span class="p">,</span> <span class="nx">url</span><span class="p">,</span> <span class="k">async</span><span class="p">,</span> <span class="nx">user</span><span class="p">,</span> <span class="nx">password</span><span class="p">);</span> <span class="nx">httpRequest</span><span class="p">.</span><span class="nx">withCredentials</span> <span class="o">=</span> <span class="kc">true</span> <span class="c1">// Cookies oder Auth-Infos mitschicken</span> <span class="nx">httpRequest</span><span class="p">.</span><span class="nf">abort</span><span class="p">();</span> <span class="nx">httpRequest</span><span class="p">.</span><span class="nf">setRequestHeader</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="p">);</span> <span class="nx">httpRequest</span><span class="p">.</span><span class="nf">getResponseHeader</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span> <span class="nx">httpRequest</span><span class="p">.</span><span class="nf">getAllResponseHeaders</span><span class="p">();</span> </code></pre> <p class="note right">Quelle: <a href="https://developer.mozilla.org/en-US/docs/AJAX/Getting_Started">AJAX-Einführung</a></p> </div></section> <section class="slide" id="sop"><div><h2>SOP</h2> <ul> <li>Same-Origin-Policy</li> <li>Sicherheitskonzept, das beispielsweise JavaScript und CSS untersagt, auf Objekte zuzugreifen, die von einer anderen Webseite (Origin) stammen</li> <li>Origin: Kombination aus Protokoll, Domain und Port</li> <li>Stellt ein wesentliches Sicherheitselement in allen modernen Browsern zum Schutz vor Angriffen dar</li> </ul> </div></section> <section class="slide" id="jsonp"><div><h2>JSONP</h2> <ul> <li>JSON mit Padding</li> <li>Übertragung von (JSON-)Daten über Domaingrenzen hinweg</li> <li>Sicherheitsrisiko, da beliebige Inhalte übermittelt werden können</li> <li>Bei strikter REST-Umsetzung nur lesender Zugriff möglich</li> </ul> </div></section> <section class="slide" id="jsonp-1"><div><h2>JSONP</h2> <pre class="highlight language-js" data-lang="js"><code><span class="kd">function</span> <span class="nf">callMe</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="p">{</span> <span class="nf">alert</span><span class="p">(</span><span class="dl">"</span><span class="s2">Dateiinhalt: </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">text</span><span class="p">);</span> <span class="c1">// andernfalls JSON.parse(text);</span> <span class="p">}</span> <span class="kd">var</span> <span class="nx">script</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nf">createElement</span><span class="p">(</span><span class="dl">"</span><span class="s2">script</span><span class="dl">"</span><span class="p">);</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">/path/to/my.js</span><span class="dl">"</span><span class="p">;</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nf">appendChild</span><span class="p">(</span><span class="nx">script</span><span class="p">);</span> <span class="c1">// my.js</span> <span class="nf">callMe</span><span class="p">(</span><span class="dl">"</span><span class="s2">Lorem ipsum dolor sit amet</span><span class="dl">"</span><span class="p">);</span> </code></pre> </div></section> <section class="slide" id="cors"><div><h2>CORS</h2> <ul> <li>Cross-Origin Resource Sharing</li> <li>Mechanismus, um Webbrowsern Cross-Origin-Requests zu ermöglichen</li> <li>Wird durch speziellen HTTP-Header vom Server gestattet</li> <li>Mit XHR 2 möglich</li> </ul> <pre class="highlight language-" data-lang=""><code>Access-Control-Allow-Origin: http://example.de Access-Control-Expose-Headers: X-Custom-Header, X-Another-Header Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: HEAD, PUT, DELETE </code></pre> <footer> <ul> <li>Simple requests Only uses GET, HEAD or POST. If POST is used to send data to the server, the Content-Type of the data sent to the server with the HTTP POST request is one of <code class="language-plaintext highlighter-rouge">application/x-www-form-urlencoded</code>, <code class="language-plaintext highlighter-rouge">multipart/form-data</code>, or <code class="language-plaintext highlighter-rouge">text/plain</code>.</li> <li>Preflighted requests Anders als <q>simple requests</q>; <q>preflighted</q> requests senden zuerst ein HTTP OPTIONS an die Ressource, um herauszufinden, welche Methoden sicher benutzbar sind. Preflight wird benutzt, wenn nicht GET oder POST (und damit Auswirkungen auf vorhandene Daten möglich sind) oder wenn eigene Header-Felder verwendet werden.</li> </ul> </footer> </div></section> <section class="slide" id="successor-fetch"><div><h2>Successor: <code class="language-plaintext highlighter-rouge">fetch</code></h2> <pre class="highlight language-js" data-lang="js"><code><span class="nf">fetch</span><span class="p">(</span><span class="dl">'</span><span class="s1">/some/url</span><span class="dl">'</span><span class="p">)</span> <span class="p">.</span><span class="nf">then</span><span class="p">(</span><span class="nx">response</span> <span class="o">=></span> <span class="p">{</span> <span class="c1">// success</span> <span class="p">}).</span><span class="k">catch</span><span class="p">(</span><span class="nx">err</span> <span class="o">=></span> <span class="p">{</span> <span class="c1">// something went wrong</span> <span class="p">});</span> </code></pre> <p class="note right">Quelle: <a href="http://www.deanhume.com/Home/BlogPost/a-basic-guide-to-the-fetch-api/10129">deanhume.com</a></p> </div></section> <section class="slide" id="fetch"><div><h2><code class="language-plaintext highlighter-rouge">fetch</code></h2> <pre class="highlight language-js" data-lang="js"><code><span class="k">async</span> <span class="kd">function</span> <span class="nf">getUser</span><span class="p">()</span> <span class="p">{</span> <span class="k">try</span> <span class="p">{</span> <span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nf">fetch</span><span class="p">(</span><span class="dl">'</span><span class="s1">https://api.example.com/user/1</span><span class="dl">'</span><span class="p">);</span> <span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">response</span><span class="p">.</span><span class="nf">json</span><span class="p">();</span> <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span> <span class="p">}</span> <span class="k">catch </span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Error fetching user:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span> <span class="p">}</span> <span class="p">}</span> </code></pre> </div></section> <section class="slide" id="fetch-1"><div><h2><code class="language-plaintext highlighter-rouge">fetch</code></h2> <pre class="highlight language-js" data-lang="js"><code><span class="k">async</span> <span class="kd">function</span> <span class="nf">createPost</span><span class="p">(</span><span class="nx">title</span><span class="p">,</span> <span class="nx">content</span><span class="p">)</span> <span class="p">{</span> <span class="k">try</span> <span class="p">{</span> <span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nf">fetch</span><span class="p">(</span><span class="dl">'</span><span class="s1">https://api.example.com/posts</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span> <span class="na">method</span><span class="p">:</span> <span class="dl">'</span><span class="s1">POST</span><span class="dl">'</span><span class="p">,</span> <span class="na">headers</span><span class="p">:</span> <span class="p">{</span> <span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">application/json</span><span class="dl">'</span> <span class="p">},</span> <span class="na">body</span><span class="p">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nf">stringify</span><span class="p">({</span> <span class="nx">title</span><span class="p">,</span> <span class="nx">content</span> <span class="p">})</span> <span class="p">});</span> <span class="k">if </span><span class="p">(</span><span class="o">!</span><span class="nx">response</span><span class="p">.</span><span class="nx">ok</span><span class="p">)</span> <span class="k">throw</span> <span class="k">new</span> <span class="nc">Error</span><span class="p">(</span><span class="s2">`HTTP error! status: </span><span class="p">${</span><span class="nx">response</span><span class="p">.</span><span class="nx">status</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span> <span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">response</span><span class="p">.</span><span class="nf">json</span><span class="p">();</span> <span class="k">return</span> <span class="nx">data</span><span class="p">;</span> <span class="p">}</span> <span class="k">catch </span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Error creating post:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span> <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> </code></pre> <footer> <ul> <li>Support derzeit in Firefox, Chrome und Opera</li> </ul> </footer> </div></section> <section class="slide" id="links"><div><h2>Links</h2> <ul> <li><a href="http://www.json.org">json.org</a></li> <li><a href="http://api.jquery.com/jquery.ajax/">jQuery.ajax()</a></li> <li><a href="https://apigee.com/about/">apigee.com</a></li> </ul> </div></section>