AJAX
- Webová interaktivní prezentace
- Klávesa "?" zobrazí krátkou nápovědu
- Tisk jako obykle
- Pro pokračování stiskněte mezerník
Obsah
- High-level: HTTP požadavek
- Ukázka API XMLHttpRequest
- Problematika asynchronnosti
- AJAX
- Problematika UTF-8
High-level: HTTP požadavek
- Všechny HTTP metody: GET, POST, HEAD, PUT, MKCOL, PROPGET, …
- Hlavičky požadavku: některé prohlížeč, některé uživatel
- Tělo požadavku: dle uživatele, UTF-8
- Hlavičky odpovědi: všechny k dispozici
- Tělo odpovědi: k dispozici jako UTF-8, v dobrých prohlížečích i bez kódování
CORS: jak obejít cross-domain restriction
- Požadavky do jiné domény jsou normálně zakázány
- Technika CORS povolí takový požadavek, pokud s ním vzdálený server souhlasí
- Informace o souhlasu předávány pomocí nových HTTP hlaviček
- Podporuje většina prohlížečů (kromě IE7, Opery)
Ukázka API XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.open("post", "/search", true); /* async */
xhr.setRequestHeader("A", "B");
xhr.send("field1=value1&field2=value2");
Změna stavu – callback
var zmenaStavu = function() {
/* zde je mozno pracovat s odpovedi, pokud nejaka dorazila */
}
xhr.onreadystatechange = zmenaStavu;
xhr.send(...);
Zpracování odpovědi
var zmenaStavu = function() {
/* tento callback se vola v kontextu instance XMLHttpRequestu */
if (this.readyState != 4) { return; }
if (this.status != 200) {
alert("HTTP/" + this.status);
return;
}
alert(this.responseText);
}
Problematika asynchronnosti
- Metoda
xhr.send()
zpravidla neblokuje
- Jediný způsob práce s požadavkem je pomocí callbacku
- JS interpret pracuje v jednom vlákně:
xhr.onreadystatechange = function() { alert("..."); }
xhr.send();
while (1) {};
- Callback se vykonává v kontextu instance
- Důsledek: komplikované workaroundy
Problémy s kontextem
Řešení #1: procpat kontext pomocí uzávěry
Map.prototype.search = function() {
var self = this;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
var response = this.responseText;
self.showResults(response);
}
xhr.send();
}
Problémy s kontextem
Řešení #2: bind
Map.prototype.search = function() {
var xhr = new XMLHttpRequest();
var response = function() {
var response = xhr.responseText; /* kde se vzalo XHR? */
this.showResults(response);
}
response = response.bind(this);
xhr.onreadystatechange = response;
xhr.send();
}
Problémy s kontextem
Řešení #3: (privátní) vlasnost
Map.prototype.response = function() {
var response = this._xhr.responseText;
this.showResults(response);
}
Map.prototype.search = function() {
this._xhr = new XMLHttpRequest();
this._xhr.onreadystatechange = this.response.bind(this);
this._xhr.send();
}
AJAX
- Za určitých podmínek je k dispozici vlastnost
xhr.responseXML
xhr.responseXML instanceof XMLDocument
- Užitečné metody pro práci se stromem (getElementsByTagName, getAttribute, …)
- Téměř identické s HTML dokumentem
- Podmínky pro vznik responseXML:
Content-type: text/xml
nebo application/xml
- Odpověď musí být well-formed XML
- Nenumerické entity jen
&
, <
, >
, "
, '
- Platné kódování (pokud nespecifikováno v značce
<?xml>
, pak UTF-8)
Problematika UTF-8
- V JS není žádný datový typ určený pro binární data
- Lze je ukládat do pole:
var binary = [192, 193];
- Lze je ukládat do řetězce:
var binary = String.fromCharCode(192, 193);
- Odpověď XMLHttpRequestu je zpracovávána jako posloupnost bytů v UTF-8
- Nejbezpečnější je použít jen dolních 128 bytů (base64)
- Alternativně hodnoty > 128 zapsat v UTF-8:
var response = [195, 128, 195, 129];
- Dobré prohlížeče umí na byty v odpovědi nahlížet jako na Unicode code pointy