O modelo que passou a ser conhecido como Ajax, termo criado por Jesse James Garrett, ficou famoso após o lançamento do GMail, a capacidade de obter recursos remotos sem precisar dar um refresh na página, modificou toda a forma de pensar no desenvolvimento web. A interface de usuário saía de uma estrutura puramente estática e passou a ser semelhante ao ambiente desktop.
Sua implementação é possível por causa do objeto javascript XMLHttpRequest que faz uma conexão assíncrona ao servidor e permite que o usuário continue seu trabalho sem bloquear a página. Na época não era especificado ainda pelo W3C.
O XMLHttpRequest surgiu como uma implementação proprietária da Microsoft e posteriormente criado no Mozilla em 2002, logo seguido pelos demais Browsers. A interface definida pelo W3C será o objeto de estudo desse artigo.
Uma conexão remota de forma assíncrona segue o seguinte esquema:
- Um evento é disparado para dar início a execução;
- Um objeto XMLHttpRequest é criado e configurado;
- Uma requisição de um recurso é feita para o servidor;
- O servidor realizada sua lógica de negócio e devolve o recurso na forma de texto comum (que deve ser um xml em formado);
- Uma função de callback, previamente informada, manipula os dados retornados;
- A renderização ao usuário é realizada.
A criação e configuração do objeto, como o envio de requisição pelo XMLHttpRequest para a captura de um recurso remoto segue os seguintes passos:
//instancia um novo objeto var ajax = new XMLHttpRequest(); //Configura uma function para a manipulação //da reposta ajax.onreadystatechange = handler; //abre a conexão ajax.open("GET", "test.xml"); //envia a requisição ajax.send(); |
Caso a conexão seja pelo método “POST”, o método send recebe como parâmetro, as variáveis a serem enviadas.
Criação do objeto
A Microsoft só implementou a interface XMLHttpRequest como um objeto nativo a partir do Internet Explorer 7, antes disso o objeto era um ActiveX. Apesar que os métodos e propriedades haviam sido copiados desse ActiveX, garantindo o funcionamento idêntico a todos os Browsers que suportam o XMLHttpRequest.
Então para as versões anteriores do IE, há a necessidade de criação customizada, eis:
var http; try { //cria o objeto caso o Browser //seja compatível com o W3C http = new XMLHttpRequest(); } catch(e) { //caso IE < IE7 //array com versões conhecidas //de implementações do ActiveX var msxml = [ 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP']; for ( var i=0, len = msxml.length; i < len; ++i ) { try { //varre o array até identificar qual ActiveX http = new ActiveXObject(msxml[i]); break; } catch(e) {} } } |
Conhecendo a Interface
Representação da Interface
interface XMLHttpRequest { // event handler attribute EventListener onreadystatechange; // state const unsigned short UNSENT = 0; const unsigned short OPEN = 1; const unsigned short SENT = 2; const unsigned short LOADING = 3; const unsigned short DONE = 4; readonly attribute unsigned short readyState; // request void open(in DOMString method, in DOMString url); void open(in DOMString method, in DOMString url, in boolean async); void open(in DOMString method, in DOMString url, in boolean async, in DOMString user); void open(in DOMString method, in DOMString url, in boolean async, in DOMString user, in DOMString password); void setRequestHeader(in DOMString header, in DOMString value); void send(); void send(in DOMString data); void send(in Document data); void abort(); // response DOMString getAllResponseHeaders(); DOMString getResponseHeader(in DOMString header); readonly attribute DOMString responseText; readonly attribute Document responseXML; readonly attribute unsigned short status; readonly attribute DOMString statusText; }; |
Event Listener
A Interface XMLHttpRequest possui um EventListener denominado “onreadystatechange“, que é um manipulador de eventos que é invocado quando o evento readystatechange é acionado. Passamos uma função de tratamento a esse EventListener que verificará os estados da conexão.
//obtem uma instancia var ajax = new XMLHttpRequest(); //seta o EventListener com o handler ajax.onreadystatechange = function() { //testa se já recebeu e foi com sucesso if(this.readyState == 4 && this.status == 200) { //obtem o xml enviado pelo servidor var xml = this.responseXML; } }; |
Propriedades
A Interface possui uma propriedade denominada “readyState” que recebe o valor de uma constante que representa o estado atual da conexão. As constantes que representam os estados são definidos como:
- UNSENT = 0; //Apenas instanciado
- OPEN = 1; //aberta
- SENT = 2; //enviada
- LOADING = 3; //abrindo
- DONE = 4; //realizada
A propriedade “status” da Interface, representa o código de status do protocolo HTTP enviado pelo servidor, como o código “200” para uma requisição com sucesso. Caso o recurso não esteja disponível, é lançado uma exceção INVALID_STATE_ERR pelo Browser. A lista de “HTTP Status Code” você encontra aqui.
A propriedade “statusText“, é a mensagem texto do “HTTP status code”, e é recebida logo após ele, como “Not Found” para o “status code” 404, que indica que o recurso não foi encontrado no servidor de destino.
As propriedades “responseText” e “responseXML“, devolvem a resposta do servidor na forma de uma DOMString (texto) e Document (da especificação DOM) respectivamente, em outras palavras, devolve um texto puro no caso do responseText ou um xml parseado no caso do responseXML.
Métodos
O método “abort” cancela a requisição, entretanto ele percorre uma série de atividades dependendo do estado da requisição no momento que é invocado. Para uma explanação mais apropriada no mecanismo que o abort realizada, visite esse link da especificação da Interface.
O método “open” é overloaded na Interface, apesar de não existir overloading em javascript. Leve em consideração que é um só, na implementação o número de argumentos passados tem a ver com a funcionalidade dependente do método, exemplo, os parâmetros “user” e “password” são necessários apenas no caso de url restrita no servidor, e caso o parâmetro “async” não seja definido, a conexão é assíncrona por default. Os primeiro parâmetro representa o método HTTP de requisição, que pode ser dos tipos: POST, GET, PUT, HEAD, DELETE e OPTIONS. O segundo parâmetro é a url que receberá a requisição, o terceiro, quarto e quinto são opcionais como já falado.
O método “setRequestHeader” é usado antes do método “send” e habilita enviar informações de cabeçalho na requisição quando for disparado os recursos ao servidor.
O método “send” envia a requisição com o argumento opcional “data” que é do tipo “Text” ou “Document”.
Quando o método de requisição escolhido é o GET, os argumentos a serem enviados ao servidor é usado no parâmetro “url”, como “/pagina.jsp?id=1&nome=milfont”. Já no método POST, os dados serão enviados como argumento do método “send”
Código completo de uma submissão Ajax
var http; try { http = new XMLHttpRequest(); } catch(e) { var msxml = [ 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP']; for ( var i=0, len = msxml.length; i < len; ++i ) { try { http = new ActiveXObject(msxml[i]); break; } catch(e) {} } } http.onreadystatechange = function() { if(this.readyState == 4 && this.status == 200) { var xml = this.responseXML; } }; var params = "id=1&name=milfont"; http.open("POST", "pagina.jsp"); http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); http.setRequestHeader("Content-length", params.length); http.setRequestHeader("Connection", "close"); http.send(params); |
Para mais features nas próximas versões da especificação mas que já podem existir nas implementações, visite esse link.
Quem quer aprender a utilizar AJAX, essa é a solução. Exemplo bastante didático e prático, mostrando todas as características necessárias para construir códigos utilizando AJAX.
Excelente post. 🙂
Pingback: Frameworks Ajax - CMilfont Tech
Pingback: Anibal Mantovani Diniz, MSc » Uma introdução ao conceito de Ajax
ótimo post!
agora só uma duvida:
estou enviando uma mensagem como: ‘este eh meu email’
sendo q o formulario esta concatenando as palavras: ‘esteehmeuemail’
o que pode ser?
valew…
Pingback: JSONRequest para evitar o “Eval” - CMilfont Tech
olá.
eu estava usando o XmlHttpRequest e ele estava ‘concatenando’ os dados do post, como eu tinha dito num comentario anterior.
eu resolvi isso com a função encodeUri() do javascript.
seu post me ajudou como usar o XmlHttpRequest num envio via method=post.
otimo post! continue assim.
vlew
Pingback: Resumo javascript - Jan 2008 - CMilfont Tech
Ótimo artigo!
Pingback: Ajax Crossbrowser no IE8 e FF3 - CMilfont Tech
Ótimo post! Muito esclarecedor… Vai ajudar um bocado em diversas implementações.