Você está na página 1de 32

Tecnologias Web 2013/14

Asynchronous JavaScript and XML (AJAX)


Departamento de Cincia de Computadores Faculdade de Cincias da Universidade do Porto

Rui Prior

AJAX 1

Comunicao com o servidor


Ciclo tradicional de interaco cliente/servidor
Utilizador insere informao numa pgina HTML, normalmente atravs de formulrios A submisso do formulrio gera um novo pedido ao servidor O servidor processa o pedido e, em resposta, gera uma nova pgina HTML A nova pgina recebida pelo navegador e exibida ao utilizador

Problemas com o ciclo tradicional


Entre o instante em que submetido o pedido e a exibio da nova pgina, a interface fica "congelada" (pedido sncrono)
Muito incomodativo se o servidor demorar a responder

A nova pgina tem que ser completamente gerada e transmitida, ainda que as alteraes sejam mnimas As aplicaes tradicionais so pesadas e pouco interactivas
AJAX 2

AJAX
No uma nova tecnologia, mas um novo paradigma para aplicaes web
O navegador troca informao com o servidor de forma assncrona, mantendo a interface funcional O servidor apenas tem que gerar a informao nova, e no pginas completas

Quando a resposta recebida, o JavaScript actualiza a pgina recorrendo ao DOM


Aplicaes web dinmicas e responsivas

Baseado em tecnologias existentes


(X)HTML para a interface CSS para a formatao e apresentao JavaScript para a dinmica (utilizando o DOM) XML para troca de informao com o servidor
Alternativas: texto simples, JSON
AJAX 3

AJAX: aplicaes
Algumas aplicaes tpicas para o AJAX
Validao em tempo real (no servidor) de campos de formulrios Autocompletao (e.g., Google autosuggest) Carregamento parcial a pedido Submisso parcial sem refrescamento da pgina completa Controlos e efeitos sofisticados, semelhantes aos usados em aplicaes locais Refrescamento de dados e server push Mashups
AJAX 4

AJAX: vantagens e inconvenientes


Vantagens
Interactividade Separao de dados, estrutura, apresentao e dinmica Menor largura de banda utilizada

Inconvenientes
Dificuldade de integrao com algumas funes do browser (histria, boto retroceder, bookmarks) Percepo da latncia da rede Maior dificuldade de anlise dos contedos
Dificuldade de indexao de contedos por sites de busca

Incompatibilidades entre implementaes do JavaScript nos diferentes navegadores


AJAX 5

XMLHttpRequest
API que permite efectuar pedidos HTTP a partir do JavaScript Retorna um objecto com as seguintes propriedades
readyState estado do pedido
0 1 2 3 4 = no-inicializado = aberto = pedido enviado = a receber resposta = resposta recebida

onreadystatechange handler para evento de alterao do readyState status quando chega a resposta, contm o cdigo de resposta HTTP statusText quando chega a resposta, contm a descrio textual do cdigo de resposta HTTP responseText corpo da resposta como string responseXML corpo da resposta como objecto DOM de tipo documento (apenas vlido em respostas XML)
AJAX 6

XMLHttpRequest: mtodos
open(method, url [, async [, username [ , password]]]) especifica o mtodo HTTP, o URL e alguns parmetros opcionais do pedido async indica se o pedido deve ser assncrono (true se omitido) username, password para efeitos de autenticao setRequestHeader(name, value) adiciona cabealho HTTP ao pedido

send(content) envia o pedido com content como corpo (null se o mtodo for o GET)
abort() cancela o pedido corrente getResponseHeader(headerName) devolve contedo do cabealho especificado getAllResponseHeaders() devolve string com todos os cabealhos HTTP

A assincronia evita o "congelamento" da interface espera da resposta. Pode fazer-se carregamento parcial sincronamente (mas pouco comum).
AJAX 7

AJAX com XMLHttpRequest: exemplo


var req = new XMLHttpRequest(); req.open("get", "/cgi-bin/add?a=5&b=7", true); req.onreadystatechange = function() { if (req.readyState != 4) { return; } Assncrono if (req.status != 200) { // Tratamento de erro (e.g., mostrar mensagem de erro) return; } var serverResponse = req.responseText; // Utilizao do resultado } req.send(null);

AJAX 8

Codificao no URL
H caracteres que so invlidos numa query string necessrio codificar os parmetros usando encodeURIComponent()
req.open("get", "/cgi-bin/register?" + "username=" + encodeURIComponent(user) + "password=" + encodeURIComponent(pass), true);

Espaos nos componentes tambm podem ser codificados com + em vez de %20 Posteriormente, pode usar-se a funo encodeURI() para codificar o URL completo
E.g., para fazer o escape de pathnames com espaos
var url = encodeURI('http://mysite.com/file with spaces.html');
AJAX 9

XMLHttpRequest com POST


var params = "a=5&b=7"; var req = new XMLHttpRequest(); req.open("post", "/cgi-bin/add", true); req.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); req.onreadystatechange = function() { if (req.readyState != 4) { return; } if (req.status != 200) { // Tratamento de erro (e.g., mostrar mensagem de erro) return; } var serverResponse = req.responseText; // Utilizao do resultado } req.send(params);

preciso ter no javascript o contedo a enviar


Pode ser uma string ou um documento XML DOM

Como o JavaScript no tem acesso ao sistema de ficheiros*, no era possvel enviar ficheiros usando este mtodo
Com HTML5 j possvel, mas sob controlo do utilizador
AJAX 10

iFrame Escondida
Inline frames (iFrames) so elementos que permitem embeber um documento HTML dentro do documento HTML principal possvel carregar documentos na iFrame sem afectar a pgina principal

A iFrame pode tornar-se invisvel

O carregamento de uma pgina na iFrame no bloqueia a interface da pgina principal Neste caso, serve apenas para carregar informao

possvel ao JavaScript da pgina principal aceder ao contedo da iFrame

Essa informao pode ser o resultado da execuo de um script do lado do servidor

iFrames escondidas so uma alternativa ao XMLHttpRequest() para implementar o paradigma AJAX

Respeitando as restries de segurana e privacidade do JavaScript

Em casos especiais, como o upload de ficheiros, antes do HTML5 era necessrio usar iFrames em vez do XMLHttpRequest()
AJAX 11

AJAX com iFrames: exemplo


<head> <script type="text/javascript"> function processResult(obj) { var doc = obj.contentWindow.document; var res = doc.getElementsByTagName("result")[0].getAttribute("value"); var ph = document.getElementById("placehold"); var tn = document.createTextNode(res); ph.replaceChild(tn, ph.firstChild); } </script> </head> <body> <iframe name="myIframe" src="about:blank" style="width:0px;height:0px" frameborder="0" onload="processResult(this)"> </iframe> <form name="myForm" action="/cgi-bin/mycgi" method="post" target="myIframe"> <!-- Definio do formulrio --> </form> <p>Result=<span id="placehold">&nbsp;</span></p> </body>
AJAX 12

Scripts dinmicos
Como qualquer outro elemento, um <script> pode ser criado e inserido dinamicamente atravs do DOM O script avaliado no momento da sua insero
Se no for inline, feito o GET do URL no atributo src

Em vez de um URL esttico, o atributo src pode conter um URL que invoca um servio remoto
Mais uma alternativa para a invocao assncrona de servios

Ao contrrio dos mtodos descritos anteriormente, a origem do script no relevante


Este mtodo permite invocar servios noutros sites A invocao de servios noutros sites tem implicaes de segurana e/ou privacidade

O script pode incluir uma chamada a uma funo de callback, que vai processar o resultado assim que este acaba de ser recebido
AJAX 13

AJAX com scripts dinmicos: exemplo


<head> <script type="text/javascript"> function createScript(a, b) { var script = document.createElement("script"); script.setAttribute("type", "text/javascript"); script.setAttribute("src", "/cgi-bin/add?a=" + a + "&b=" + b + "&cb=processResult"); // funo de callback scriptid = createUniqueId(); // varivel global script.setAttribute("id", scriptid); // para posteriormente o remover document.getElementsByTagName("head")[0].appendChild(script); } function processResult(result) { var ph = document.getElementById("placehold"); var tn = document.createTextNode(result); ph.replaceChild(tn, ph.firstChild); var script = document.getElementById(scriptid); script.parentNode.removeChild(script); // j no mais necessrio => remove-o } </script> </head> <body> <script type="text/javascript"> createScript(5, 7); </script> <p>Result=<span id="placehold">&nbsp;</span></p> </body> processResult(12); // resposta do servidor cdigo JavaScript!!! (Cuidado!) AJAX 14

Comparao dos trs mtodos


Vantagens do XMLHttpRequest
Nmero virtualmente ilimitado de pedidos em simultneo
Funcionamento assncrono (multithreaded) Compatvel com XHTML Strict

Vantagens dos iFrames


Permite o upload de ficheiros*

Vantagens dos scripts dinmicos


Possibilidade de acesso a servios de terceiros (cross-site)*

Inconvenientes dos scripts dinmicos


Apenas mtodo GET Necessrio cuidado com aspectos de segurana e privacidade

NOTA: O XMLHttpRequest nvel 2 (HTML5) permite submisso de ficheiros e acesso a servios de terceiros
AJAX 15

Cross-Origin Resource Sharing


Originalmente, o XMLHttpRequest no podia ser usado para obter servios doutro site
Conduzindo ao uso (potencialmente inseguro) do mtodo de scripts dinmicos

Em browsers recentes (HTML5), o standard CORS possibilita XMLHttpRequests a sites diferentes


Sujeitos a algumas restries

Trs cenrios de utilizao


Simples Preflighted Com credenciais
AJAX 17

CORS: Simples
Apenas GET ou POST com contedo text/plain, application/x-www-form-urlencoded ou multipart/form-data Sem cookies, autenticao ou cabealhos no-standard
GET /resources/public-data/ HTTP/1.1 Host: otherserver.com [outros cabealhos ...] Origin: http://myserver.com Identificao do site original HTTP/1.1 200 OK [outros cabealhos ...] Access-Control-Allow-Origin: * Transfer-Encoding: chunked Content-Type: application/xml [outros cabealhos ...] [contedo da resposta]
AJAX 18

Servidor aceita pedidos feitos a partir de qualquer site original (recurso pblico)

CORS: Preflighted
Restantes mtodos e POST com outros tipos de contedo Sem cookies nem autenticao, pode ter cabealhos no-standard Consulta prvia (OPTIONS) ao servidor para determinar se seguro fazer o pedido que se pretende script invocado 2 vezes!!!
OPTIONS /resources/post-here/ HTTP/1.1 Host: otherserver.com [outros cabealhos ...] Origin: http://myserver.com Access-Control-Request-Method: POST Pedido vai ser feito com mtodo POST Access-Control-Request-Headers: MY-CUSTOM-HEADER e vai ter um cabealho

no-standard
HTTP/1.1 200 OK [outros cabealhos ...] Access-Control-Allow-Origin: http://myserver.com Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: Content-Type, MY-CUSTOM-HEADER Access-Control-Max-Age: 1728000
AJAX 19

CORS: Com credenciais


Envio de cookies e/ou cabealhos de autenticao
Simples ou preflighted Activa-se atravs da propriedade withCredentials do objecto XMLHttpRequest
var xhr = new XMLHttpRequest(); ... xhr.withCredentials = "true"; ... # Activa CORS com credenciais

AJAX 20

CORS: Com credenciais


GET /resources/public-data/ HTTP/1.1 Host: otherserver.com [outros cabealhos ...] Referer: http://myserver.com/corscredtest.html Origin: http://myserver.com Cookie: SESSID=acbd18db4cc2f85cedef654fccc4a4d8

Se a resposta no tiver os cabealhos necessrios, o browser no a passa ao objecto XMLHttpRequest Access-Control-Allow-Origin tem que ser o servidor original
HTTP/1.1 200 OK [outros cabealhos ...] Access-Control-Allow-Origin: http://myserver.com Access-Control-Allow-Credentials: true Content-Type: application/xml [outros cabealhos ...] [contedo da resposta]
AJAX 21

CORS: Notas sobre segurana


Em pedidos simples com credenciais, o script no servidor corrido mesmo que no retorne os cabealhos necessrios
Apenas no browser a resposta no passada ao objecto XMLHttpRequest

Este problema no exclusivo do CORS, j era possvel fazer o mesmo com a submisso de formulrios Soluo: scripts "sensveis" devem verificar sempre o contedo do cabealho Referer (e do Origin, se existir)
AJAX 22

Formatos para a troca de informao


Texto simples: text/plain
Valores simples, pares chave=valor, formatos proprietrios Conciso e eficiente, sobretudo para valores simples Necessrio parsing se no forem apenas valores simples

XML: text/xml ou application/xml


Formato standard para a troca de informao Muito verboso Necessrio parsing, que pesado no caso do XML Acessvel atravs do DOM ou da extenso E4X

JSON (JavaScript Object Notation): application/json


Objectos JavaScript serializados Conciso e eficiente Parsing opcional apenas para aumentar segurana (e.g., JSON.parse)
Ou simplesmente eval() (fortemente desaconselhado)
AJAX 23

XML no cliente
Gerao
// Criao de rvore DOM com o documento XML var doc = document.implementation.createDocument(null, 'root', null); var root = doc.documentElement; var element = doc.createElement('element'); root.appendChild(element); element.appendChild( document.createTextNode('Some text here') ); // Serializao do documento numa string XML var xmlString = (new XMLSerializer()).serializeToString(doc);

Parsing de XML para uma rvore DOM


Com XMLHttpRequest basta aceder ao mtodo responseXML

Carregamento de XML contido num ficheiro


xmlDoc.load('myfile.xml'); // IE e FireFox

Carregamento de XML contido numa string


xmlDoc = (new DOMParser()).parseFromString(s, "text/xml"); // S FireFox
AJAX 24

JSON
Formato leve para a troca de dados

Subconjunto da definio de literais em JavaScript


JSON JavaScript
{ "firstName": "John", "lastName": "Smith", "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": 10021 }, "phoneNumbers": [ "212 732-1234", "646 123-4567" ] }
Exemplo extrado da Wikipedia AJAX 25

JSON

Fonte: www.json.org

AJAX 26

JSON no cliente
Objecto JSON (nativo no HTML5 ou mdulo json2)

Gerao
var JSONstring = JSON.stringify(obj);

Parsing
Com eval (perigoso no usar)
var obj = eval('(' + JSONstring + ')');

Com parser (objecto JSON)


var obj = JSON.parse(myJSONtext);

Parser permite converso de dados


var obj = JSON.parse(text, function (key, value) { return key.indexOf('date') >= 0 ? new Date(value) : value; });
AJAX 27

Texto Simples vs. XML vs. JSON


Formato
Texto Simples Conciso Flexvel Simples

Vantagens

Inconvenientes
Com mais que um valor
Que formato usar? Necessrio implementar parser especfico

XML

Standard Grande capacidade expressiva Muito verboso Humanamente legvel Parsing pesado Possibilita validao do formato (DTD)
No necessita de parser no cliente ( JavaScript) Conciso Permite serializar objectos Menos suportado que o XML noutras linguagens alm do JavaScript
AJAX 28

JSON

Invocao de procedimentos remotos


Aplicao web duas partes
Cdigo CGI (ou similar) corre no servidor
Acesso base de dados, etc.

Cdigo JavaScript corre no cliente

Interagem apenas atravs da troca de mensagens em pedidos/respostas HTTP Como invocar funes/subrotinas no servidor a partir do JavaScript?
AJAX 29

Invocao de procedimentos remotos soluo bsica


No cliente:
function remote_add(a, b) { var req = new XMLHttpRequest(); req.open("get", "/my/script?ACTION=add&a=" + a + "&b=" + b, true); req.onreadystatechange = function() { if (req.readyState != 4) { return; } if (req.status != 200) { alert('ERROR'); // Tratamento de erros importante return; } alert(a + '+' + b + '=' + req.responseText); } req.send(); }

Se os parmetros puderem ter caracteres especiais preciso codific-los com encodeURIComponent()


AJAX 30

Invocao de procedimentos remotos JSON-RPC (v2.0)


Pedido
{ "jsonrpc": "method": "params": "id": "2.0", "add", [5, 7], 3241 }

Parmetros com nome


{ "jsonrpc": "method": "params": "id": "2.0", "add", { "term1": 5, "term2": 7 }, 3241 }

Resposta bem sucedida


{ "jsonrpc": "2.0", "result": 12, "id": 3241 }

Resposta de erro
{ "jsonrpc": "2.0", "error": { "code": -32601, "message": "Procedure not found." }, "id": 3241 }
AJAX 31

Invocao de procedimentos remotos JSON-RPC


Mdulo json-rpc cliente sncrono
var service = new JsonRpc.ServiceProxy("/cgi-bin/math", { asynchronous: false, methods: [ 'add' ] }); alert(service.add(5, 7));

Invocao pode falhar lanando excepo melhor faz-la num bloco try/catch
try { var result = service.calc.add(5,7); alert(result); } catch (e) { alert("Unable to add numbers because: " + e); }
AJAX 32

Invocao de procedimentos remotos JSON-RPC


Mdulo json-rpc cliente assncrono (prefervel)
var service = new JsonRpc.ServiceProxy("/cgi-bin/math", { asynchronous: true, methods: [ 'add' ] });

service.add( { params: [5, 7], onSuccess: function(sum) { alert(sum); }, onException: function(e) { alert("Unable to add numbers because: " + e); } } );

AJAX 33

Você também pode gostar