AJAX

Wikikirjastosta
Siirry navigaatioon Siirry hakuun

Tämä kirja perustuu W3Cn luonnokseen The XMLHttpRequest Object (2008-04-15)


Wikipedia
Wikipedia-tietosanakirjassa on artikkeli aiheesta:

AJAX eli Asynchronous JavaScript And XML (asynkroninen JavaScript ja XML) on yhdistelmä eri tekniikoita, joiden avulla voidaan siirtää tietoa asiakasohjelman (client), yleensä selain (browser), ja palvelimen (server) välillä ilman, että koko WWW-sivua täytyy ladata uudelleen.

AJAXilla voidaan luoda tavanomaisten, kokonaan yksittäisessä tietokoneessa suoritettavien, tietokoneohjelmien tapaisia sovelluksia mutta joita käytetään WWWn välityksellä. Tällöin esimerkiksi useat käyttäjät voivat käsitellä samaa tiedostoa. Lisäksi AJAXilla voidaan vähentää resurssien tarvetta suhteessa suoritettuun toimintoon, koska siirretään vain muutos ei koko sivua joka muutoksella. Data selaimen ja serverin välillä siirtyy taustalla asynkronisesti.

AJAX käyttää seuraavia tekniikoita

  • JavaScript - paikallinen prosessointi
  • XML - tiedon esittäminen
  • XHTML - tiedon esittäminen
  • CSS - tiedon ulkoasu
  • DOM - sivun sisältämän datan haku
  • XMLHTTPRequest-olio - datan lukemiseen ja lähettämiseen selaimen ja serverin välillä asynkronisesti

Lisäksi tarvitaan jokin palvelinpuolen ohjelmointikieli kuten

AJAX perustuu seuraaviin standardeihin

W3C: XML 1, HTML 4, DOM 2, CSS 2, XMLHttpRequest (luonnos), HTTP 1.1. (statuskoodit: 404 etc)
ECMA: ECMAScript 1.5. (JavaScript)

XMLHTTPRequest-objekti[muokkaa | muokkaa wikitekstiä]

AJAX perustuu XMLHttpRequest-olioon. Oliona sillä on ominaisuuksia ja metodeja.

XMLHttpRequest-olion ominaisuudet
Ominaisuus Kuvaus
onreadystatechange tapahtumankäsittelijä, joka kutsuu määriteltyä funktiota kun vastaus on saatu palvelimelta
readyState XMLHTTPRequest-objektin tila
responseText käsittelee haetun datan merkkijono-muotoisena
responseXML käsittelee haetun datan XML-muotoisena
status 200 kun pyynnön suoritus onnistunut
404 kun sivua ei löydy
statusText palauttaa statuksen merkkijonona

readyState-ominaisuudella on viisi eri tilaa, jotka kertovat, missä vaiheessa suoritusta pyyntö on menossa. Tilat ovat

0 = ei ole alustettu
1 = yhteys muodostettu
2 = pyyntö vastaanotettu
3 = vastausta prosessoidaan
4 = valmis
XMLHttpRequest-olion metodit
Metodi Kuvaus
abort() keskeyttää pyynnön
setRequestHeader("name", "value") Lisää nimi/arvo -parin lähetettävään HTTP ylätunnisteeseen (header)
getResponseHeader("name") palauttaa tietyn HTTP ylätunnisteen (header) merkkijonona
getAllResponseHeaders() palauttaa kaikki HTTP ylätunnisteet (headers) merkkijonona
open("method", "URL", async) Pyynnön määritysten antaminen
send(data) Lähettää pyynnön. data voi olla merkkijono tai viittaus dokumenttiin

Pyynnön lähettäminen palvelimelle (parametrina lähetettävä data, mikäli käytetään POST-metodia)

open metodilla annetaan pyynnön määrityksiä, joista kolme tärkeintä ovat

  • method, jolla valitaan datan palvelimelle lähetyksen tyypiksi GET- tai POST
  • URL, johon kirjoitetaan pyynnön vastaanottavan serveriskriptin suhteellinen tai absoluuttinen url-osoite
  • async, jolla asetetaan asynkroninen siirto päälle (true) tai pois päältä (false)

send-metodilla lähetään pyyntö palvelimelle. Mikäli käytetään POST-tapaa välittää tieto selaimelta palvelimelle, tulee send-metodin parametriksi lähetettävä data, muutoin null.

POST ja GET[muokkaa | muokkaa wikitekstiä]

POST ja GET ovat kaksi erilaista tapaa siirtää tietoa selaimelta palvelimelle ja päinvastoin. Niiden käyttö eroaa hivenen toisistaan.

GET-tavalla data siirtyy URL-osoitteen mukana.

POST-tavalla data siirtyy HTTP-otsikkotietojen mukana.

Datan siirtäminen selaimen ja palvelimen välillä[muokkaa | muokkaa wikitekstiä]

Koodi tulee XHTML-tiedoston head-osioon <script type="text/javascript"></script>-tagien väliin.

Ensiksi esitellään globaali muuttuja XMLHTTPRequest-objektille eli luodaan instanssi.

// Esitellään muuttuja XMLHTTPRequest-objektille: 
var Pyynto;


Muuttuja alustetaan omassa funktiossaan.

// Alustetaan Pyynto-muuttuja 
function alustaPyynto() 
{ 
     Pyynto = new XMLHttpRequest(); 
}

suoritaPyynto-funktioista toteutetaan joko GET- tai POST-tavalla ei molemmilla.

Määritellään funktio varsinaisen pyynnön suorittamiselle GET-tavalla.

// Käytetään GET-tapaa datan välittämiseen palvelimelle 
function suoritaPyynto() 
{ 
    // Alustetaan Pyynto-muuttuja kutsumalla edellä toteutettua funktiota
    alustaPyynto(); 

    // Määritellään funktio, joka suoritetaan, kun vastaus palvelimelta on saapunut
    Pyynto.onreadystatechange = kasitteleVastaus;   // HUOM: funktion nimi ilman sukeita

    // Käytetään GET-tapaa datan lähettämiseen asynkronisesti 
    // palvelimelle serveriskripti.php-nimiselle skriptille
    Pyynto.open("GET", "serveriskripti.php?nimi=Arvo", true); 

    // Lähetetään pyyntö palvelimelle
    Pyynto.send(null); 
}

Määritellään funktio varsinaisen pyynnön suorittamiselle POSP-tavalla.

// Käytetään POST-tapaa data välittämiseen palvelimelle 
function suoritaPyynto() 
{ 
    // Alustetaan ensin Pyynto-muuttuja kutsumalla edellä toteutettua funktiota
    alustaPyynto(); 

    // Määritellään funktio, joka suoritetaan, kun vastaus palvelimelta on saapunut
    Pyynto.onreadystatechange = kasitteleVastaus; 

    // Käytetään POST-tapaa datan lähettämiseen asynkronisesti
    // palvelimelle serveriskripti-nimiselle skriptille: 
    Pyynto.open("POST", "serveriskripti.php", true); 
     
    // Asetetaan HTTP-otsake kertomaan sisällön tyyppi
    Pyynto.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 

    // Lähetetään pyyntö palvelimelle
    Pyynto.send("nimi=Arvo"); 
}

POST-tavassa lähetettävä data annetaan parametriksi send-metodille. Tällöin on myös asetettava HTTP-otsake "Content-Type", joka kertoo serveriskriptille minkälaista tietoa on tulossa.

Kun lähetetään useampia arvoja erotetaan ne toisista ampersandilla (&)

    // Lähetetään pyyntö palvelimelle
    Pyynto.send("nimi1=Arvo1"&"nimi2=Arvo2");

Sovelluksen toteutus aloitetaan eli kutsutaan suoritaPyynto-funktiota, vaikkapa jollain tapahtumankäsittelijällä. Seuraavalla koodilla sovellus käynnistetään painiketta napsauttamalla.

<input type="button" value="Suorita sovellus" onclick="suoritaPyynto()" />

Kun vastaus on saatu suoritetaan kasitteleVastaus-funktio, joka kutsutaan onreadystatechange-metodilla.

function kasitteleVastaus() 
{ 
    // Tarkistetaan, onko pyyntö suoritettu kokonaan
    if(Pyynto.readyState == 4) 
    { 
        // Tarkistetaan, onko pyynnön suoritus onnistunut
        if(Pyynto.status == 200) 
        { 
            // Jos kaikki on kunnossa, käsitellään saapunut data
            alert(Pyynto.responseText); 
        } 
        else 
        { 
            alert("Pyynnön suorituksessa on tapahtunut virhe!"); 
        } 
    } 
}

Funktiossa tarkistetaan ensin, onko pyyntö suoritettu kokonaisuudessaan, jolloin readyState-ominaisuuden arvoksi tulee 4. Tämän jälkeen tutkitaan, onko pyynnön suorittaminen onnistunut vai onko tapahtunut virhe. Onnistunut pyynnön suorittaminen asettaa status-ominaisuuden arvoksi 200. Sen sijaan esimerkiksi virhekoodi 404 kertoo, ettei annetusta osoitteesta löytynyt sivua (skriptiä).

Palvelimen lähettämä data saadaan poimittua esille responseText-ominaisuudesta, joka sisältää datan tekstimuotoisena.

Kun data on vastaanotettu, sen jatkokäsittely tapahtuu muiden tekniikoiden kuten JavaScript ja DOM avulla.

Koko esimerkki GET-tavalla:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 
<head>
        <title>Sivun otsikko</title>
        <meta http-equiv="content-type" 
                content="text/html;charset=utf-8" />
        <meta http-equiv="Content-Style-Type" content="text/css" />

<script type="text/javascript">//koko esimerkki GET-tavalla
// Esitellään muuttuja XMLHTTPRequest-objektille: 
var Pyynto;

// Alustetaan Pyynto-muuttuja 
function alustaPyynto() 
{ 
     Pyynto = new XMLHttpRequest(); 
}

// Muodostetaan funkito, jota käytetään haettuun dataan
function kasitteleVastaus() 
{ 
    // Tarkistetaan, onko pyyntö suoritettu kokonaan
    if(Pyynto.readyState == 4) 
    { 
        // Tarkistetaan, onko pyynnön suoritus onnistunut
        if(Pyynto.status == 200) 
        { 
            // Jos kaikki on kunnossa, käsitellään saapunut data
            alert(Pyynto.responseText); 
        } 
        else 
        { 
            alert("Pyynnön suorituksessa on tapahtunut virhe!"); 
        } 
    } 
}

// Käytetään GET-tapaa datan välittämiseen palvelimelle 
function suoritaPyynto() 
{ 
    // Alustetaan Pyynto-muuttuja kutsumalla edellä toteutettua funktiota
    alustaPyynto(); 
 
    // Määritellään funktio, joka suoritetaan, kun vastaus palvelimelta on saapunut
    Pyynto.onreadystatechange = kasitteleVastaus;   // HUOM: funktion nimi ilman sukeita
 
    // Käytetään GET-tapaa datan lähettämiseen asynkronisesti 
    // palvelimelle serveriskripti.php-nimiselle skriptille
    Pyynto.open("GET", "serveriskripti.php?nimi=Arvo", true); 
 
    // Lähetetään pyyntö palvelimelle
    Pyynto.send(null); 
}

</script>

</head>
 
<body>
 
Sisältö
 
</body>
</html>

XML-muotoisen datan käsittely[muokkaa | muokkaa wikitekstiä]

XML-datan käsittely tapahtuu pääosin DOM-mallin metodeja ja ominaisuuksia hyödyntämällä. Kun data lähetetään palvelimelta XML-muotoisena, on palvelimella suoritettavan skriptin alussa kerrottava lähetettävän datan tyyppi. PHP-kielessä tämä tapahtuu seuraavasti.

<?php 
// Asetetaan HTTP-otsake, jossa kerrotaan palvelimen selaimelle lähettämän tiedon tyyppi: 
header("Content-type: text/xml"); 

// Tähän varsinainen skripti 
?>

Lähetettävän datan on oltava XML-standardin mukaista.


<?xml version="1.0" encoding="utf-8"?> 
<henkilot> 
    <henkilo> 
        <nimi>Matti</nimi> 
        <osoite>Paratiisitie 13</osoite> 
    </henkilo> 
    <henkilo> 
        <nimi>Maija</nimi> 
        <osoite>Parasiitie 14</osoite> 
    </henkilo> 
</henkilot>

XML-datan elementteihin pääsee käsiksi DOM-metodeilla ja -ominaisuuksilla. getElementsByTagName-metodilla voidaan XML-datasta hakea vaikkapa kaikki osoite-elementit taulukkoon. Jokaisella osoite-elementillä lapsinodet, joihin päästään käsiksi childNodes-ominaisuuden avulla. Seuraava esimerkki havainnollistaa asiaa.

var osoitteet = Pyynto.responseXML.getElementsByTagName("osoite"); 
var osoite = osoitteet[0].childNodes[0].nodeValue;

Kaikki osoite-nimiset elementit haetaan osoitteet-taulukkoon ja sitten osoitteet-taulukosta otetaan ensimmäinen osoite-elementti (osoitteet[0]), ja sen ensimmäinen lapsisolmu (childNodes[0]). Tämän solmun arvo "Paratiisitie 13" löytyy nodeValue-ominaisuudesta.