Blog webdeveloperski Patryk yarpo Jar

[Ajax] Obiekt XMLHttpRequest

Autor wiadomości Marzec 7, 2011

Poniższy artykuł będzie o wykorzystaniu obiektu XMLHttpRequest do wysyłania asynchronicznych żądań ze strony www do serwera.

Jeśli nie wiesz, czym jest Ajax, warto przeczytać:

Co na początek?

Aby móc uruchomić przykłady zawarte w tym artykule potrzebujesz:

  • serwera www [np. Wamp]
  • przeglądarki www [np. Firefox]
  • przydatny może być edytor [np. Geany]
  • około 10 minut

Jeśli chciałbyś, aby Twoje skrypty wykorzystujące Ajax działały również po IE6, warto zapoznać się z artykułem o odpowiedniej łacie:

Obiekt XMLHttpRequest

Według specyfikacji w3c obiekt ten posiada takie pola:

XMLHttpRequest = {
    onreadystatechange;
    open(string method, string url, boolean async);
    setRequestHeader(string header, string value);
    send(mixed data);
    abort();
    status;
    statusText;
    getResponseHeader(string header);
    getAllResponseHeaders();
    responseText;
    responseXML;
};

Niektóre z nich mogą być przeciążane, ale to można doczytać w dokumentacji.

Najprostszy działający przykład

Ponieważ chcę pokazać istotę Ajax wszystkie przykłady będą operować na zwracanych danych typu 'plain-text'. Istnieje także możliwość operowania na XML, poprzez `responseXML'. Temat ten poruszyłem we wpisie o XML. Warto także zapoznać się z (moim zdaniem) lepszym formatem dla Ajaksa - JSON.

Kod PHP (działający po stronie serwera):

<?php echo "Witaj świecie!"; ?>

Zapisz ten kod do pliku 'ajax.php'.

Kod strony (JS + HTML):

<html>
<head>
    <title>Przykład Ajax</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <script type="text/javascript">
    function ajaxTest()
    {
        var client = new XMLHttpRequest();
        client.open('POST', 'ajax.php', false);
        client.send(null); // ważna linia
        alert(client.responseText);
    }
    </script>
</head>
<body><div onclick="ajaxTest()" id="content">Kliknij mnie</div></body>
</html>

Powyższy kod pozwala na wyświetlenie w alercie teksu uzyskanego z serwera. Jak widać wszystko, co zostanie wyświetlone w skrypcie po stronie serwera trafia do zmiennej `client.responseText'.

Był to przykład na synchroniczne żądanie Ajax. Synchroniczne, czyli takie, w którym w linii oznaczonej komentarzem "ważna linia" będzie czekał na odpowiedź. Metoda ta jest polecana tylko w sytuacjach, kiedy musimy być pewni, w jakiej kolejności zostaną wykonane żądania.

Częściej wykorzystuje się żądania asynchroniczne, o który mowa niżej.

Żądania asynchroniczne

W przypadku żądań asynchronicznych, skrypt nie wstrzyma działania strony. Strona będzie działać normalnie, a w tle będzie obsługiwany Ajax. Wymagane są do tego tzw. funkcje callback. Zobaczmy przykład (w skrypcie 'ajax.php' nic się nie zmienia).

<html>
<head>
    <title>Przykład Ajax</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <script type="text/javascript">
    function ajaxTest()
    {
        var client = new XMLHttpRequest();
        client.open('POST', 'ajax.php', true); // asynchronicznie
        client.send(null);
        // zdefiniuj callback
        client.onreadystatechange = function()
        {
            // 200 = OK, 4 = odczytano, tu: this = client
            if (200 === this.status && 4 === this.readyState)
            {
                alert('status: ' + this.statusText + '\n' +
                                   this.responseText);
            }
        }
    }
    </script>
</head>
<body><div onclick="ajaxTest()" id="content">Kliknij mnie</div></body>
</html>

Co zmieniło się w porównaniu z poprzednim kodem?

client.open('POST', 'ajax.php', true);

Ostatni parametr ustawiony na true oznacza: "żądanie asynchroniczne".

Dodatkowo przypisaliśmy funkcję obsługującą zdarzenie readystatechange:

client.onreadystatechange = function() { ... }

Funkcja ta będzie wywoływana do obsługi wyniku zwróconego przez serwer.

Dziwne kody?

Czy są tajemnicze 200 oraz 4 z listingu? Już tłumaczę. Pole XMLHttpRequest.readyState może przyjmować wartości:

0 - nieustawiony
1 - otwarty
2 - otrzymano nagłówki
3 - ładowanie
4 - odczytano

Skoro chcieliśmy odczytać jakieś dane sprawdzamy, czy już jest wartość 4. Nie spotkałem się z przypadkiem, w którym upragnionym stanem byłby inny - chyba, że dla przykładu akademickiego.

A czymże jest 200? Jest to kod HTTP. 200 oznacza "wszystko w porządku" - a przecież tego chcemy.

Inne, często spotykane kody:

W pozostałych przykładach, będę korzystał z żądań asynchronicznych.

Przesyłanie danych na serwer

Najczęściej występuje potrzeba wysłania danych na serwer. Jak to zrobić?

Zmieńmy kod 'ajax.php':

<?php echo "Wynik: " . (intval($_POST['n']) + intval($_POST['k'])); ?>

W kodzie JS też potrzebne są zmiany:

<html>
<head>
    <title>Przykład Ajax</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <script type="text/javascript">
    function ajaxTest()
    {
        var client = new XMLHttpRequest();
        client.open('POST', 'ajax.php', true); // asynchronicznie
        // odpowiedni typ [aby moc wysylac dane]
        client.setRequestHeader('Content-Type',
                   'application/x-www-form-urlencoded; charset=UTF-8');
        // wyslij dane
        client.send('n=2&k=3');
        client.onreadystatechange = function()
        {
            if (200 === this.status && 4 === this.readyState)
            {
                alert('status: ' + this.statusText + '\n' +
                                   this.responseText);
            }
        }
    }
    </script>
</head>
<body><div onclick="ajaxTest()" id="content">Kliknij mnie</div></body>
</html>

W wyniku powinniśmy otrzymać 5. Oczywiście można wysłać inne dane. W przypadku metody POST dane wysyłamy jako ciąg znaków przekazywanych do funkcji `send'. Ciąg znaków może zawierać wiele danych, wg schematu:

nazwa_zmiennej_1=wartość_x&nazwa_zmiennej_2=wartość_y

Przesyłane mogą być zarówno liczby, jak i ciąg znaków (dla HTTP wszystko i tak jest ciągiem znaków). Na serwerze odbieramy to identycznie jak w przypadku wysłanego formularza, a więc:

<?php echo $_POST['nazwa_zmiennej']; ?>

W przypadku metody GET jest trochę inaczej.

Przesyłanie danych za pomocą GET

Jak najprościej odróżnić metodę GET od POST? GET przesyła dane w adresie, np. example.com?zmienna=wartosc&zmienna2=wartosc. Więcej o GET można przeczytać na wikipedii.

Po stronie serwera zmieni się jedynie nazwa tablicy superglobalnej, z której odczytujemy dane POST -> GET.

<?php echo "Wynik: " . (intval($_GET['n']) + intval($_GET['k'])); ?>

W kodzie JS zmieni się też niewiele:

function ajaxTest()
{
    var client = new XMLHttpRequest();
    client.open('GET', 'ajax.php?n=2&k=3', true);
    client.send(null);
    client.onreadystatechange = function()
    {
        if (200 === this.status && 4 === this.readyState)
        {
           alert('status: ' + this.statusText + '\n' +
                              this.responseText);
        }
    }
}

Jak widać, ponownie do metody `send' przekazujemy null. Dodatkowo duże zmiany zaszły w linii:

client.open('GET', 'ajax.php?n=2&k=3', true);

Jest to zobrazowanie tego, o czym pisałem wcześniej. POST zmieniliśmy na GET, a także wszystkie zmienne przesyłane na serwer są podawane w adresie, jako parametry. Pamiętaj o oddzieleniu właściwego adresu od parametrów znakiem zapytania '?'.

Ograniczenia GET

Ilość danych przekazywanych do serwera jest ograniczona maksymalną długością adresu (długość ta zależy od ustawień serwera).

Warto przeczytać

Korzystanie na "gołego" obiektu XMLHttpRequest nie jest zbyt wygodne. Polecam zapoznanie sie z możliwymi ułatwieniami:

Komentarze (0) Trackbacks (0)

Przepraszam, dodawanie komentarzy zablokowane.

Trackbacks are disabled.