Home
Navigation
Impressum
SEO Welten - Webcoding, Editoren, Scripte und Anwendungen
SEO Welten
Buchempfehlungen
 

Ajax: Mehrere Requests nacheinander ausführen

Ajax-Requests entsprechend einer festgelegten Reihenfolge ausführen

Übersicht / Seite:

  1. Content mit Ajax verarbeiten (eine kleine Einführung)

    5.1 Verarbeitung von XML-Dateien (Attribute einlesen und ausgeben)
    5.2 Mehrere Requests ausführen (Requests hintereinander abarbeiten)
    5.3 Parallel Requests ausführen (Anfragen gleichzeitig senden)


Domainübergreifende Kommunikation mit Ajax

Auf der vorausgehenden Seite wurde eine Möglichkeit vorgestellt, um mit JavaScript und Ajax eine XML-Datei einzulesen, den Inhalt auszuwerten und auszugeben. Dabei wurde jedoch auf eine Datei zugegriffen, die auf dem eigenen Server lag und unter derselben Domain wie die aufrufende, den Ajax-Code enthaltende Datei erreichbar war. Ein wenig komplizierter wird die Angelegenheit, wenn auf eine Datei zugegriffen werden soll, die nicht auf dem eigenen, sondern auf einem entfernten Server liegt.
Durch die Sicherheitseinstellungen der Browser würde eine direkte, durch ein clientseitiges Script ausgelöste Anfrage scheitern, insofern ein Datenaustausch zwischen unterschiedlichen Domains angestrebt wird. Entsprechend der Same-Origin-Policy (SOP) soll Cross-Site-Scripting (XSS) durch unlautere Zeitgenossen möglichst verhindert werden, um ein Ausspähen oder die Manipulation von fremden Daten zumindest zu erschweren. Die Kehrseite dieses Sicherheitskonzeptes sei ebenfalls erwähnt. Nicht nur Hacker müssen nach anderen Lösungen suchen, sondern auch Programmierer, die mit JavaScripts oder Ajax-Anwendungen einen domainübergreifenden Datenaustausch realisieren möchten.

Für die Realisierung einer domainübergreifenden Kommunikation mit Hilfe von JavaScript und Ajax gibt es unterschiedliche Lösungsansätze. Eine recht simple Lösung besteht darin, auf dem eigenen Server ein Script abzulegen, welches nicht nur die Anfragen vom clientseitigen Script entgegennimmt, sondern auch den Austausch von Daten mit einem entfernten Server regelt. Genauer betrachtet handelt es sich dabei um ein kleines Proxy-Script, welches eine Schnittstelle für die Kommunikation und für den Datenaustausch mit einem entfernten Server enthält.
Soll von einer Ajax-Anwendung nicht nur ein Request ausgeführt werden, sondern mehrere Requests gleichzeitig oder der Reihe nach hintereinander, wird die Angelegenheit noch ein wenig komplizierter. Dazu im nachfolgenden Beispiel mehr.

Serverseitige Umsetzung: Requests senden und Response auswerten

Für die Umsetzung sind mindestens zwei Dateien erforderlich, wobei es sich bei der einen Datei um eine einfache HTML-Seite mit einem kleinen Ajax-Script handelt und bei der anderen Datei um ein simples PHP-Script, welches in die Rolle eines Proxys schlüpft. Damit das Beispiel nicht zu einfach wird, wurde die Aufgabenstellung im Exempel noch ein wenig erweitert. So sollen nicht nur nicht nur mehrere Anfragen an unterschiedliche Domains gesendet werden, sondern die Antworten (Response) zusätzlich noch unterschiedlich ausgewertet werden.

Eine kleine Vorbemerkung. Um die einzelnen Web-Adressen mit Ajax an ein serverseitiges Script weiterzuleiten, könnten die jeweiligen URLs zum Beispiel als Parameter-Werte im QueryString übergeben werden.

Beispiel, URL als Parameter-Wert übergeben:

testseite.php?url=www.example.com/unterseite.html

Diese Art der Übergabe erleichtert die eigentliche Umsetzung jedoch nicht unbedingt, wenn zwischen den einzelnen Domains eine Auswahl oder Unter­scheidung zu treffen ist. Weiterhin müssten zusätzliche Sicherheitsmaßnahmen getroffen werden, damit durch einfachen Austausch der Parameterwerte keine unerwünschten Seiten durch Unbefugte geladen werden können. Im Beispiel wurden aus diesem Grund auf die Übergabe von URLs verzichtet. Stattdessen erhalten alle gewünschten URLs eine eindeutige ID, womit noch weitere Vorteile verbunden sind. Diese weiteren Vorteile ergeben sich aus den Beispiel-Codes und sind mehr oder weniger selbsterklärend.

Zur Aufgabenstellung sei ergänzend bemerkt, es sollen insgesamt 5 Anfragen an 5 unterschiedliche Web-Adressen gestellt werden. Weiterhin sollen bei einzelnen Anfragen aus einigen der angeforderten Dokumente die im H1-Tag enthaltenen Überschriften und der im ersten P-Element der Dateien notierte Content ausgelesen werden. Aus anderen Dokumenten sollen hingegen nur die Seitentitel ausgelesen und für eine Ausgabe aufbereitet werden.
Zur Lösung dieser Aufgabenstellung wurden zwei Funktionen definiert, wobei die eine Funktion nur nach dem Inhalt von H1-Elementen und nach dem Inhalt des jeweils ersten P-Elementes sucht, die zweite Funktion hingegen nach dem Titel der jeweiligen Seite. Beide Funktionen greifen dabei auf eine weitere Funktion mit dem Namen "oeffneSeite" zu. Diese Funktion übernimmt den eigentlichen Verbindungs­aufbau und ladet die angeforderten Dateien als String.
Um nun zwischen den URLs unterscheiden zu können, wurden diese in ein Array notiert und mit einer fortlaufenden ID versehen. An Hand dieser ID kann mit Hilfe von IF-Statements unterschieden werden, ob die Auswertung des angeforderten Dokumentes mit der Funktion sucheH1P1() oder mit der Funktion sucheMetas() erfolgen soll.

Eine Beispieldatei als Testseite (testseite.php):

<?php
error_reporting(E_ALL);
ini_set("display_errors"true);

$feedurls = array (

    1 => "www.example.com/startseite.html",
    2 => "www.example.com/rubrikseite.html",
    3 => "www.example.com/unterseite.html",
    4 => "www.example.net/startseite.php",
    5 => "www.example.net/unterseite.php/"
);

// Auswertung, mit welcher Funktion die jeweilige zur URL gehörende Seite geholt und ausgewertet werden soll

if (isset($_GET["urlid"]) and !empty($_GET["urlid"])) {

    $urlid = preg_replace("/[^0-9]/", "", $_GET["urlid"]);

    if ($urlid == 2 or $urlid == 3 or $urlid == 5) {
        echo sucheH1P1("http://".$feedurls[$urlid]);
    }
    elseif ($urlid == 1 or $urlid == 4) {
        echo sucheMetas("http://".$feedurls[$urlid]);
    }
    else {echo "Ein Fehler trat auf!";
    }
}

// Die als URL angegebene Datei holen und in einem String lesen

function oeffneSeite($suche) {

    $option = array("http" => array("header" => "User-Agent: Mozilla/5.0 (compatible; Ajax/PHP)\r\n"));
    $agent  = stream_context_create($option);

    if (($daten = file_get_contents($suche, false, $agent)) != false) {
        return $daten;
    } else { echo "File konnte nicht geladen werden!\n";
    }
}

// Inhalt von H1 und dem ersten P-Tag auslesen

function sucheH1P1($suche) {

    $daten = oeffneSeite($suche);
    $finde = "";

    if (preg_match("/<h1.*?>(?P<titel>.+?)<\/h1>/is", $daten, $findeh)){
        $finde .= "<b>".htmlspecialchars($findeh["titel"], ENT_QUOTES)."</b><br>\n";
    } else {
        echo "Es wurde kein H1-Tag gefunden!<br>\n";
    }
    if (preg_match("/<p.*?>(?P<absatz>.+?)<\/p>/is", $daten, $findep)){
        $finde .= htmlspecialchars($findep["absatz"], ENT_QUOTES)."\n";
    } else {
        echo "Es wurde kein P-Tag gefunden!<br>\n";
    }
    return $finde;
}

// Nur den Titel der Seite auslesen

function sucheMetas($suche) {

    $daten = oeffneSeite($suche);
    $finde = "";

    if (preg_match("/<title>(?P<titel>.+?)<\/title>/is", $daten, $findeh)){
        $finde .= "<b>".htmlspecialchars($findeh["titel"], ENT_QUOTES)."</b><br>\n";
    } else {
        echo "Es wurde kein Titel gefunden!<br>\n";
    }
    return $finde;
}
?>

Das Speichern von IDs und Web-Adressen in Arrays empfiehlt sich für kleine mit mittlere Seiten mit einer überschaubaren Anzahl an externen Verbindungen. Alternativ könnten bei größeren Projekten die URLs unter einer Datenbank gespeichert und gegebenenfalls mit einigen Flags versehen werden.

Clientseitige Umsetzung: Anfragen senden

Die clientseitige Umsetzung mit HTML und Ajax gestaltet sich einfacher, auch wenn einige Punkte zu beachten sind. Grundlegendes zum Prinzip wurde bereits auf den vorausgehenden Seiten beschrieben und soll an dieser Stelle nicht wiederholt werden.
Zu beachten gilt jedoch, dass die Anfragen nicht alle gleichzeitig an ein Script gesendet werden können (Die Betonung liegt dabei auf "nicht alle", doch dazu auf der nächsten Seite mehr), sondern hintereinander abgearbeitet werden müssen. Andernfalls, zum Beispiel in einer Schleife, würde var testObj immer wieder überschrieben, was bei asynchroner Übertragung zum Datenverlust führen würde. Doch es geht auch ohne Schleife, wenn wie im Beispiel-Script vor einem neuen Request der Eingang und die Ausgabe der letzten Response abgewartet wird.

Der erste Aufruf der Funktion sendeRequest() erfolgt im Beispiel mit der Funktion window.onload(). Windows.onload bedeutet, dass ein Fenster bereits fertig geladen wurde, da sich onload in diesem Zusammenhang aufs Fenster und nicht aufs Dokument bezieht. Letzteres wäre nur dann der Fall, wenn der Event-Handler onload innerhalb des Body-Tags notiert wird. Die Funktion sendeRequest() erzeugt beim ersten Aufruf ein XMLHttpRequest Object, welches in der Variablen testObj gespeichert wird. Mit Hilfe dieses Objektes wird nun eine asynchrone Verbindung zur angegebenen Web-Adresse erstellt, insofern die angegebene Datei unter derselben Domain erreichbar ist.

Um eine eingehende Antwort auswerten und ausgeben zu können, muss eine entsprechende Funktion der Eigenschaft onreadystatechange als Funktion für den Event-Handler zugewiesen werden. Im Beispiel wurde diese Funktion für den Event-Handler mit dem Bezeichner ladeSeite() deklariert. Trifft eine Nachricht ein, wird diese onreadystatechange Event-Handler Funktion aufgerufen und zwar immer dann, wenn sich der Wert von readyState verändert.
Wie bereits auf den vorausgehenden Seiten vermerkt, so bedeutet die Ziffer 4, dass eine Antwort vollständig übermittelt wurde. Innerhalb der Funktion ladeSeite() wird der Wert von readyState mit Hilfe eines IF-Statements mit dem Vorgabewert 4 verglichen. Ist der Wert der Eigenschaft readyState gleich 4, so wird testObj.responseText ausgewertet und mit Hilfe der Eigenschaft innerHTML und der DOM-Methode getElementById() an entsprechender Stelle ins Dokument geschrieben.
Weiterhin wird der Counterstand von i um 1 erhöht und der Wert der Variablen fa auf true gesetzt. Als direkte Folge kann die Funktion sendeRequest() erneut aufgerufen werden, um eine weitere Anfrage zu senden. Zumindest solange, wie der Variablen fa der boolesche Wert true zugeordnet wird. Dieser Ablauf wird erst unterbrochen, wenn der Wert von i größer als der Wert der Variablen anzahl wird und somit der Wert der Variablen fa beim booleschen false verbleibt.

Ein kleines Demo-Script mit Ajax (ajax.html):

<!DOCTYPE html>
<html>

<head>
<title>Ein Demo-Script mit Ajax</title>
<style type="text/css">
h1 {text-align:center}
div.bereich {width:800px; margin:auto}
div.ausgabe {float:left; border:1px solid #7f4925; width:352px; margin:10px}
</style>
</head>

<body>
<h1>Ein Demo-Script mit Ajax</h1>
<!--
 Hier so viele Div-Bereiche im Dokument anlegen und mit einer ID versehen,
 wie auszuwertende Seiten geladen werden sollen.
-->
<div class="bereich">
    <div id="ausg1" class="ausgabe">Eins:<br><br></div>
    <div id="ausg2" class="ausgabe">Zwei:<br><br></div>
    <div id="ausg3" class="ausgabe">Drei:<br><br></div>
    <div id="ausg4" class="ausgabe">Vier:<br><br></div>
    <div id="ausg5" class="ausgabe">Fünf:<br><br></div>
</div>

<!-- Script-Bereich im Head oder Footer unterbringen oder auslagern -->

<script type="text/javascript">
"use strict";

var i = 1;

function sendeRequest() {

    var testObj = null;
        testObj = new XMLHttpRequest();

    testObj.open("GET", "testseite.php?urlid="+i);
    testObj.onreadystatechange = ladeSeite;
    testObj.send(null);

    function ladeSeite() {

        var fa = false;
        var anzahl = 5;      // Anzahl der zu ladenden Seiten bzw. Anzahl der URIs angeben

        if (testObj.readyState == 4) {
            document.getElementById("ausg"+i).innerHTML += testObj.responseText;
            i++;
            fa = true;
            if (i > anzahl) fa = false;
        }
        if (fa != false) sendeRequest();
    }
}

window.onload = function() {

    sendeRequest();
}
</script>
</body>
</html>

Mehr zum Thema Einbinden und Einlesen von Dateien mit HTML, PHP und JavaScript auf den folgenden Seiten.

weiterlesen: 1, 2, 3, 4, 5 « / »

 
Navigation

Finden und
gefunden werden ...


- Optimierung -

 

Webcoding

Übersicht


Web Services


Tutorials &
diverse Listings

und vieles mehr...

 

Weitere Themen

Übersicht


Copyright © 2006 - Verlag Horst Müller - Stendal | Datenschutz | Nutzungsbedingungen