2. díl - Metody GET a POST v AJAXu

JavaScript AJAX Metody GET a POST v AJAXu

V minulém díle jsme si vysvětlili k čemu nám AJAX slouží a jak zjednodušeně funguje. Z hlediska teorie je to dostatek pro kvalitní start a prvotní přehled, proto se dnes můžeme rovnou pustit do nějakých konkrétních příkladů.

Začneme velmi jednoduše. Jistě znáte metodu GET. Jde o standardní http metodu, sloužící povětšinou k získávání dat ze serveru. Samozřejmě to neznamená, že tato metoda nemůže předávat serveru data formou query, to bez problémů může a taky se toho často využívá pro specifikaci požadovaných dat. Pojďme tedy trochu kódit:

HTML soubor:

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<script>
function magic(str) {
    if (str.length == 0) {
        document.getElementById("magician").innerHTML = "";
        return;
    } else {
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            // tento kód se provede v okamžiku navrácení hodnoty ze serveru
                document.getElementById("magician").innerHTML = xmlhttp.responseText;
            }
        }
        xmlhttp.open("GET", "kouzelnik.php?param1="+str, true);
        xmlhttp.send();
    }
}
</script>
</head>
<body>
<p><b>Do inputu níže vložte volitelné číslo a nechte kouzelníka hádat!</b></p>
<form>
<input type="text" onkeyup="magic(this.value)">
</form>
<p>Kouzelník říká: <span id="magician"></span></p>
</body>
</html>

Moc se neohlížejte na sémantiku nebo validnost HTML, zapomeňte pro tentokrát na neobtruzivní kódování a jen využijte tento kód jako poměrně zřetelný příklad. Než si projdeme co se vlastně v tomto kódu děje, dodám ještě PHP zdroják.

PHP soubor:

<?php
$attr = $_GET["param1"];
echo "Myslím, že číslo, které si myslíš je: ".$attr;
?>

Zápis HTML netřeba vysvětlovat, na stránce se objeví řádek textu, jež nás vyzve k zadání čísla, input prvek, jež k zadání poslouží a opět řádek textu, jež říká: “Kouzelník říká:”. Co se však stane, když do inputu vložíme/napíšeme jakékoliv číslo či znak? V zásadě se tím spustí událost, jež očekáváme za pomocí atributu onkeyup – v okamžiku kdy stisknete klávesu se ještě nic neděje, ale v momentě kdy ji pustíte zavolá se funkce magic a jako parametr přijme současnou hodnotu inputu.

A teď k AJAXu a metodě GET:

Z minula si jistě pamatujete, že se obvykle dodržuje určité pořadí volání příkazů, hodně to napomáhá přehlednosti, ale i funkčnosti kódu*. Doporučuji dodržovat! Nás ale teď vlastně zajímají jen poslední dva řádky kódu – první je volání metody open() na objekt typu XMLHttpRequest, tato metoda provádí, jak je patrné z jejího názvu něco jako otevření spojení, nikoliv však samotné odeslání hodnot (doslova jde o inicializaci). Odeslání obstarává metoda send() na posledním řádku scriptu.

Metoda send() však nepotřebuje žádný parametr (alespoň pokud jde o GET), což nás přivádí opět k metodě open(), která přijímá tři parametry (a několik volitelných). Posledně jsem vám slíbil, že se jim budu více věnovat. Nuže tedy: prvním parametrem je typ metody, to je důležité hlavně z hlediska serverového API, ne vždy je totiž API napsáno tak, aby podporovalo 'prohazování' metod GET a POST, proto je nutné používat vždy metodu, která je vyžadována serverem. Druhým parametrem je adresa – tady se na moment zastavíme a trochu specifikujeme, díky SOP (Same Origin Policy) jsme odkázáni na stejný server/stejnou adresu domény jako má samotný index, tedy nemůžeme na stránce www.itnetwork.cz požadovat ajax request na adresu www.mojeip.cz. Proč tomu tak je a jak to obejít, (když by se tak dalo krásně spolupracovat s externími API) si vysvětlíme v jiném článku této sekce.

Zatím tedy pokud chcete spolupracovat s nějakým API na zpracování dat, musíte celý systém na zpracování dat pro server implementovat na svém serveru (nebo komunikovat s externím API pomocí serverového jazyka – JAVA, PHP, ...). Jistě jste si všimli, že posílám parametr/argument v adrese volané metodou GET nazvaný param1, obsahující string z inputu, pomocí adresy, kterou volám – to je standardní chování metody GET. Ta posílá svoje parametry pomocí tzv. queries - řetězce v těle adresy, kterou volá, má to své výhody, ale i nevýhody. Ty nechám mimo tento článek, snad jen řeknu, že nespornou výhodu je, že s GET se většinou nemusí implicitně specifikovat nic navíc ohledně dat, která posíláme (více v POSTu – níže). Pokud neznáte PHP, nebo jste nikdy nepracovali s metodou GET, zajímá vás jistě, kolik parametrů se takhle dá poslat. Teoreticky nejste omezeni konkrétním počtem parametrů, jste ale omezeni konkrétním počtem znaků (velmi dobře popsaná je tato problematika zde, nebo hledejte v češtině hesla jako url maximální počet znaků). Pro zjednodušení pracujte s faktem, že pokud budete mít celou adresu dlouhou do 2048 znaků, neměl by nastat problém v žádné variaci serveru, či klienta.

Jak tedy zmínit všechny parametry hromadně? Velmi jednoduše. Zatímco před první parametr musíte umístit znak '?' otazníku, mezi každý další umístíte znak & a poté zase napíšete název parametru, aby se dal na serveru identifikovat a jeho hodnotu za rovnítkem, takto opakujte dokud nezmíníte všechny argumenty. Třetím a posledním parametrem metody open() je booleovská hodnota, tato hodnota je velmi důležitá! Pokud ji neuvedete, defaultně se nastaví na true. Pokud ji uvedete jako false, dostanete v některých prohlížečích na konzoli varování - ano řeč je o asynchronicitě. Tato proměnná určuje, zda-li je tento AJAX požadavek prováděn asynchronně, či nikoliv. Může se to zdát poněkud zvláštní, vždyť slovo asynchronní je hned první slovo ve zkratce AJAX, nicméně je tomu tak a občase se to i hodí. Podtrženo sečteno – pokud bude hodnota uvedena jako true, bude se request provádět nezávisle na hlavním vlákně, nebude tedy blokovat průběh hlavního scriptu a nezpůsobí "zamrznutí" vašeho kódu až do příchodu odpovědi. Pokud ale bude hodnota uvedena jako false, stane se přesný opak toho, co jsem popsal o větu dříve. Znamená to, že vlastně rozšiřujete kód hlavního vlákna a úloha je tzv. blokující. Na to si dejte pozor!

Nyní AJAX a metoda POST:

Nechte si svůj původní zdroják ode mě a proveďte na něm přesně tyto změny:

  1. na předposledním řádku scriptu s metodou open() přepište první parametr z 'GET' na 'POST', vyjměte všechny vaše i moje původní atributy z adresy/z druhého parametru - v adrese musí zůstat skutečně jen relativní, nebo absolutní adresa na PHP script, smažte proto i znak '?' na konci adresy
  2. mezi poslední a předposlední řádek scriptu, tedy mezi volání metody open(), které jsme právě upravili a volání metody send(), které je na konci scriptu, vložte tento řádek kódu:
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
  1. na posledním řádku scriptu, ve volání metody send(), která dřív nepoužívala žádné parametry, připište této metodě parametr typu string, vlastně to bude string obsahující parametry, které jsme odebraly z řádku s open() metodou z jejího druhého parametru (adresy) (jediné čím se liší, je absence znaku '?' otazníku na začátku)
  • Pokud tápete, koukněte se níže na ukázku.

Výborně, právě jste přepsali váš AJAX zdroják tak, aby používal metodu POST, proveďte proto i nutnou úpravu ve zdrojáku pro server (z $_GET['param1'] udělejte $_POST['param1']). Pro názvy parametrů/atributů můžete vymyslet svoje vlastní označení dle libosti – jen dodržte stejné pojmenování v javascriptu i na serveru, třeba v PHP).

Pro zkontrolování, poslední tři řádky v JS:

xmlhttp.open("POST", "kouzelnik.php", true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("param1="+str);

a pár řádků kódu v PHP:

<?php
$attr = $_POST["param1"];
echo "Myslím, že číslo, které si myslíš je: ".$attr;
?>

Nyní si projdeme rozdíly oproti GETu - prvním velkým rozdílem je tvar adresy, při použití POSTu nikdy nepíšeme atributy/parametry do adresy (nepoužíváme query), vychází to samozřejmě z návrhu a konstrukce těchto dvou metod. Zatímco GET předává informaci/parametry v adresním řádku (pokud vám to přijde divné, doporučuji nastudovat v PHP sekci) a nehodí se tak například pro posílání hesel. POST adresní řádek nepoužívá a je také trochu více zabezpečen, pro soukromější informace/data se proto hodí o poznání více. Většinu z vás asi teď zajímá, co tam dělá ten úplně nový řádek.

Tento řádek se používá pro definování formátu dat, takovéto nastavování headeru může nejen u POSTu vypadat opravdu rozličně a komplikovaně, ideálně ho proto prozatím berte jako něco co tam je a být tam musí, pokud používáte POST. Poslední změnou je přidání parametru metodě send(), tento parametr je string se všemi atributy/parametry pro metodu POST, díky této formě odesílání máme možnost i pro POST říct serveru co chceme a nepoužít při tom adresní řádek.

To je v rámci Javasciptu všechno, změny v PHP kódu a kód samotný popisovat nebudu, na to jsou na síti mnohem fundovanější osoby.

Odzkoušení

Nyní můžeme přejít k tomu nejzábavnějšímu - vyzkoušení si příkladu, předpokládám, že jste si nějaká testování prováděli už při mém výkladu, shrnu to tedy jen velmi rychle – obě metody, jak GET tak POST jsou schopné předat informaci serveru. Díky AJAXu, resp. jeho další schopnosti můžeme také obdržet odpověď na dotaz, nicméně také nemusíme žádnou odpověď očekávat. Pro tyto případy by se hodila metoda POST, protože ta obvykle slouží k odeslání dat na server (ale někdy taky k vyžádání dat zpět), pokud chceme jen získat nějaká data, která nepodléhají bezpečnostním opatřením, můžeme klidně použít GET.

Samozřejmě je dnešní příklad pouze ilustrační – tato funkcionalita nevyžaduje PHP na serveru, nevyžaduje dokonce ani AJAX, dalo by se toho docílit pomocí Angularu, stejně tak by se to ale dalo napsat v "čistém" Javascriptu. Zkuste si ale představit, že PHP komunikuje s nějakou databází na serveru a podle toho, jakou metodu použijete a jaké argumenty/parametry pošlete, je z databáze vybrána nějaká informace a předána klientu. Zajímavé ne? Tomu už se skutečně dá říkat komunikační API. Zkuste si sami něco takového "spíchnout", jazyk pro API a typ databáze nechávám na vás.

*Dle dokumentace na MDN – pokud chceme aby kód fungoval, musíme o odchytávání události zažádat dříve, než odešleme požadavek serveru.

Závěr:

V článku jsem zmínil několik důležitých věcí, jedním z nich je SOP – nyní už znáte význam této zkratky a pro ty, které toto téma více zajímá, připravuji článek o pravidlech k dodržování a podrobnostech, jež jsou pro začínajícího AJAXáře stěžejní. Dále také připravuji článek o možnosti obejít tuto restrikci a volat za pomocí Javascriptu i externí API na cizí doméně, dokonce na volitelném portu, pokud vás tato problematika zaujala, zůstaňte naladěni ;)


 

  Aktivity (3)

Článek pro vás napsal Taskkill
Avatar
Autor se věnuje vývoji na mobilních platformách a webu. Zajímá se o všechny oblasti informačních technologií a je zapřísáhlým fanouškem Open Source. Hrdě používá OS GNU Debian a všechno co je freeware.

Jak se ti líbí článek?
Celkem (6 hlasů) :
55555


 


Miniatura
Předchozí článek
Úvod do AJAXu
Miniatura
Všechny články v sekci
AJAX
Miniatura
Následující článek
JSONP pro začátečníky

 

 

Komentáře
Zobrazit starší komentáře (8)

Avatar
Taskkill
Redaktor
Avatar
Taskkill:

Díky za upozornění na věcnou chybu. místo "txtHint" tam napiš "magician" ... a já půjdu ihned tuhle záměnu napravit.

 
Odpovědět 3.10.2015 14:21
Avatar
asoft
Člen
Avatar
asoft:

Hurá, už mi to funguje v ASP.NET MVC.
Tu sa nerobí súbor kouzelnil.asp, ale sa to odohráva v napr: HomeController

Neviem prečo predanie parametru mi nefunguje cez: Request.QueryS­tring["param1"],
"param1" je null.

Funguje to cez predanie parametru "param1" v metode.

[HttpPost]
[ActionName("Index")]
public void Index_Post(string param1)
        {
            //var attr = Request.QueryString["param1"];
            Response.Write("Myslím, že číslo, ktoré si myslíš je: " + param1);
            return;
        }
 
Odpovědět 4.10.2015 10:20
Avatar
asoft
Člen
Avatar
Odpovídá na asoft
asoft:

Neviem prečo predanie parametru mi nefunguje cez: Request.QueryS­tring["param1"],
"param1" je null.

Už mi to je jasné. Metóda GET vs POST.

Ja som to robil stále na POST. Keď som dal GET tak s úpravami v HomeController
funguje aj Request.QueryS­tring["param1"].

 
Odpovědět 4.10.2015 13:07
Avatar
Taskkill
Redaktor
Avatar
Odpovídá na asoft
Taskkill:

Výborně, jsem rád, že všechno běhá jak má a dodatečně se omlouvám za tu drobnou mistifikaci. Přeju hodně štěstí v dalším kódění ;-)

 
Odpovědět 4.10.2015 13:10
Avatar
asoft
Člen
Avatar
Odpovídá na asoft
asoft:

Takže posledná poznámka. Ide to aj pomocou súboru kouzelnik.aspx

Vďaka za spoluprácu.

 
Odpovědět 4.10.2015 15:08
Avatar
loading84
Člen
Avatar
loading84:

Ono je tam ještě jedna chyba. U způsobu přes get by měl vypadat skript takto:

<?php
$attr = $_GET["get"];  //param1 a ne get
echo "Myslím, že číslo, které si myslíš je: ".$attr;
?>
 
Odpovědět  +2 2. ledna 18:06
Avatar
Taskkill
Redaktor
Avatar
Odpovídá na loading84
Taskkill:

Diky moc, okamzite opravim.

 
Odpovědět  +2 2. ledna 19:20
Avatar
janci#3
Člen
Avatar
janci#3:

ja mám taký problém že mám AJAX funkciu ktorá mi načíta JSON objekty ale kým sa tá funkcia spraví tak mi už načíta stránku bez toho aby mi to tam zobrazilo.. vedeli by ste mi prosím poradiť ?

function getComment(){
        var xhttp = new XMLHttpRequest();
        xhttp.open("GET", "getComment?id=" + index);
        xhttp.send(null);
        xhttp.onreadystatechange = function(){
                if(xhttp.readyState == 4){
                        $scope.comments = JSON.parse(xhttp.response);
                        console.log($scope.comments);
                }
        }
        }
<div ng-repeat="x in comments">
{{x.text}}
</div>
 
Odpovědět 28. dubna 19:35
Avatar
Taskkill
Redaktor
Avatar
Odpovídá na janci#3
Taskkill:

Muzes specifikovat svuj problem? Nedokazu z tveho popisu pochopit, jestli se tvoje funkce provede a dojde k vypsani dat ve spravne podobe a az nekde dal se po pokazi, nebo vubec ne .. no nevim...

Kazdopadne si oprav tohle:

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function(){
                if(xhttp.readyState == 4){
                        $scope.comments = JSON.parse(xhttp.response);
                        console.log($scope.comments);
                }
        }
xhttp.open("GET", "getComment?id=" + index);
xhttp.send(null);

pamatuj si -> nejdriv nastavit handler a pak otevrit spojeni a poslat data...

 
Odpovědět 28. dubna 21:43
Avatar
janci#3
Člen
Avatar
Odpovídá na Taskkill
janci#3:

tak mal som problém s tým že tá funkcia mi išla dobre len trvala dlhšie ako načítanie stránky čiže výsledky mi zobrazilo až po reloadnutí stránky ale už som to vyriešil jednou funkciou

function getComment(vypis){
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function(){
                if(xhttp.readyState == 4){
                        vypis(JSON.parse(xhttp.response));
                }
        }
        xhttp.open("GET", "getComment?id=" + index);
        xhttp.send(null);

        }
        getComment(function(data) {
                var i;
                for(i = 0; i<data.length;i++){
                        $("#commentsDiv").append(data[i].text);
                }

a opravil som si aj ten handler ďakujem za radu :)

 
Odpovědět 29. dubna 22:03
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 18. Zobrazit vše