Presentació Ajax

179 views
125 views

Published on

Presentació d'Ajax.

Més manuals a: http://www.exabyteinformatica.com

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
179
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Presentació Ajax

  1. 1. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/Presentació d’AjaxLa història dAJAX està íntimament relacionada amb un objecte de programació anomenatXMLHttpRequest. Lorigen daquest objecte es remunta a lany 2000, amb productes comExchange 2000, Internet Explorer 5 i Outlook Web Access.Tot va començar al 1998, quan Alex Hopmann i el seu equip es trobaven desenvolupant lallavors futura versió d’Exchange 2000. El punt feble del servidor de correu electrònic era el seuclient via web, anomenat OWA (Outlook Web Access).Durant el desenvolupament de OWA, es van avaluar dues opcions: un client format només perpàgines HTML estàtiques que es recarregaven constantment i un client realitzat completamentamb HTML dinàmic DHTML. Alex Hopmann va poder veure les dues opcions i es va decantarper la basada en DHTML. No obstant això, per ser realment útil aquesta última, li faltava uncomponent essencial: quelcom que evités haver denviar contínuament els formularis ambdades al servidor.Motivat per les possibilitats futures de OWA, Alex va crear en un sol cap de setmana la primeraversió del que va anomenar XMLHTTP. La primera demostració de les possibilitats de la novatecnologia va ser un èxit, però faltava el més difícil: incloure aquesta tecnologia en elnavegador Internet Explorer.Si el navegador no incloïa XMLHTTP de forma nativa, lèxit del OWA shauria reduïtenormement. El major problema és que faltaven poques setmanes perquè es llancés lúltimabeta dInternet Explorer 5 prèvia al seu llançament final. Gràcies als seus contactes enlempresa, Alex va aconseguir que la seva tecnologia sinclogués en la llibreria MSXML queinclou Internet Explorer.De fet, el nom de lobjecte (XMLHTTP) es va triar per tenir una bona excusa que justifiqués laseva inclusió en la llibreria XML dInternet Explorer, ja que aquest objecte està molt mésrelacionat amb HTTP que amb XML.Desenvolupar aplicacions AJAX requereix un coneixement avançat de totes i cadascuna de lestecnologies de programació.En les aplicacions web tradicionals, les accions de lusuari a la pàgina (punxar en un botó,seleccionar un valor duna llista, etc.) desencadenen cridades al servidor. Una vegadaprocessada la petició de lusuari, el servidor retorna una nova pàgina HTML al navegador delusuari.Aquesta tècnica tradicional per crear aplicacions web que funcioin correctament, però, no creauna bona sensació a lusuari. En realitzar peticions contínues al servidor, lusuari ha desperaral fet que es recarregui la pàgina amb els canvis sol·licitats. Si laplicació ha de realitzarpeticions contínues, el seu ús es converteix en quelcom molest.
  2. 2. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/Ajax permet millorar completament la interacció de lusuari amb laplicació, evitant lesrecarregues constants de la pàgina, ja que lintercanvi dinformació amb el servidor es produeixen un segon pla.Les aplicacions construïdes amb Ajax eliminen la recarrega constant de pàgines mitjançant lacreació dun element entremig de lusuari i el servidor. La nova capa intermitja dAjax millora laresposta de laplicació, ja que lusuari mai es troba amb una finestra del navegador buidaesperant la resposta del servidor.Les peticions HTTP al servidor es substitueixen per peticions Javascript que es realitzen alelement encarregat dAjax. Les peticions més simples no requereixen intervenció del servidor,per la qual cosa la resposta és immediata. Si la interacció requereix una resposta del servidor,la petició es realitza de forma asíncrona mitjançant Ajax. En aquest cas, la interacció de lusuaritampoc es veu interrompuda per recarregues de pàgina o llargues esperes per la resposta delservidor.Des de la seva aparició, shan creat centenars daplicacions web basades en Ajax. En la majoriade casos, Ajax pot substituir completament a altres tècniques com a Flash. A més, en el cas deles aplicacions web més avançades, poden arribar a substituir a les aplicacions descriptori.A continuació es mostra una llista dalgunes de les aplicacions més conegudes basades en Ajax:· Gestors de correu electrònic: Gmail, Yahoo Mail i Windows Live Mail entre d’altres.· Cartografia: Google Maps, Yahoo Maps i Windows Live Local entre d’altres.· Aplicacions web i productivitat: Google Docs, Zimbra i Zoho entre d’altres.Unes altres: Netvibes, Digg (notícies), Meebo (missatgeria), 30 Boxes (calendari), Flickr(fotografia).Anàlisis detallatUna aplicació Ajax es compon de quatre grans blocs: instancia del objecte XMLHttpRequest,preparar la funció de resposta, realitzar la petició al servidor i executar la funció de resposta.Totes las aplicacions realitzades amb tècniques d’Ajax reben una instància en primer lloc delobjecte XMLHttpRequest, que és l’objecte clau que permet realitzar comunicacions amb elservidor en segon pla, sense necessitat de recarregar les pàgines.La implementació del objecte XMLHttpRequest depen de cada navegador, per tant ésnecessari fer servir una discriminació senzilla en funció del navegador en el que se estàexecutant el codi:if(window.XMLHttpRequest) { // Navegadors que segueixen els estàndarspeticio_http = new XMLHttpRequest();}
  3. 3. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/else if(window.ActiveXObject) { // Navegadors obsoletspeticio_http = new ActiveXObject("Microsoft.XMLHTTP");}Els navegadors que segueixen els estàndars (Firefox, Safari, Opera, Internet Explorer 7, 8, 9 i10) implementen l’objecte XMLHttpRequest de forma nativa, pel que es pot obtenir a travésde l’objecte window. Els navegadores obsolets (Internet Explorer 6 i anteriors) implementenl’objecte XMLHttpRequest com un objecte de tipus ActiveX.Una vegada obtinguda l’instancia del objecte XMLHttpRequest, es prepara la funció que s’eencarrega de processar la resposta del servidor. La propietat onreadystatechange del objecteXMLHttpRequest permet indicar aquesta funció directament inserint el ssu codi mitjançantuna funció anònima o indicant una referència a una funció independent. En l’exemple anteriors’indica directament el nom de la funció:peticio_http.onreadystatechange = mostraContingut;El codi anterior indica que quan l’aplicació rebi la resposta del servidor, s’ha d’executar lafunció mostraContingut(). Como és habitual, la referència a la funció s’indica mitjançant el seunom sense parèntesis, ja que d’una altra manera s’estaria executant la funció iemmagatzemant el valor retornat en la propietat onreadystatechange.Després de preparar l’aplicació per al retorn del servidor, es realitza la petició HTTP alservidor:peticio_http.open(GET, http://localhost/prova.txt, true);peticio_http.send(null);Les instruccions anteriors realitzen el tipus de petició més senzilla que es pot enviar al servidor.En concret, es tracta d’una petició del tipus GET simple que no envia cap paràmetre alservidor. La petició HTTP es crea mitjançant el mètode open(), en el que s’inclou el tipus depetició GET, la URL sol·licitada (http://localhost/prova.txt)i un tercer paràmetre amb el valorTrue.Una vegada creada la petició HTTP, s’envia al servidor mitjançant el mètode send(). Aquestmètode inclou un paràmetre que en l’exemple anterior té el valor Null.Per últim, quan es rep la resposta del servidor, l’aplicació executa de forma automàtica lafunció establerta anteriorment.function mostraContingut() {if(peticio_http.readyState == 4) {if(peticio_http.status == 200) {
  4. 4. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/alert(peticio_http.responseText);}}}La funció mostraContingut() comprova en primer lloc que sha rebut la resposta del servidor(mitjançant el valor de la propietat readyState). Si sha rebut esposta, es comprova que siguivàlida i correcta (comprovant si el codi destat HTTP retornat és igual a 200). Una vegadarealitzades les comprovacions, simplement es mostra per pantalla el contingut de la respostadel servidor (en aquest cas, el contingut de larxiu sol·licitat) mitjançant la propietatresponseText.Refactoritzant la primera aplicacióLa primera aplicació AJAX mostrada anteriorment presenta algunes mancances importants. Acontinuació, es refactoritza el seu codi ampliant-ho i millorant-ho perquè sadapti millor aaltres situacions. En primer lloc, es defineixen unes variables que sutilitzen en la funció queprocessa la resposta del servidor:var READY_STATE_UNINITIALIZED = 0;var READY_STATE_LOADING = 1;var READY_STATE_LOADED = 2;var READY_STATE_INTERACTIVE = 3;var READY_STATE_COMPLETE = 4;Com es veurà més endavant, la resposta del servidor només pot correspondre a algun dels cincestats definits per les variables anteriors. Daquesta forma, el codi pot utilitzar el nom de cadaestat en comptes del seu valor numèric, per la qual cosa es facilita la lectura i el mantenimentde les aplicacions.A més a més, la variable que emmagatzema la instància de lobjecte XMLHttpRequest estransforma en una variable global, de manera que totes les funcios que fan ús daquest objectetinguin un accés directe sobre el mateix:var peticio_http;A continuació, es crea una funció genèrica de carga de continguts mitjançant Ajax:
  5. 5. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/function cargaContenido(url, metode, funcio) {peticio_http = inicialitza_xhr();if(peticio_http) {peticio_http.onreadystatechange = funcio;peticio_http.open(metode, url, true);peticio_http.send(null);}}La funció definida admet tres paràmetres: la URL del contingut que es va a carregar, el mètodeutilitzat per realitzar la petició HTTP i una referència a la funció que processa la resposta delservidor.En primer lloc, la funció carregaContingut() inicialitza lobjecte XMLHttpRequest (anomenat xhrde forma abreujada). Una vegada inicialitzat, sempra lobjecte peticio_http per establir lafunció que processa la resposta del servidor. Finalment, la funció carregaContingut() realitza lapetició al servidor emprant la URL i el mètode HTTP indicats com a paràmetres.La funció inicialitza_xhr() sempra per encapsular la creació de lobjecte XMLHttpRequest:function inicialitza_xhr() {if(window.XMLHttpRequest) {return new XMLHttpRequest();}else if(window.ActiveXObject) {return new ActiveXObject("Microsoft.XMLHTTP");}}La funció mostraContingut() també se refactoritza per a emprar les variables globals definides:function mostraContingut() {
  6. 6. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/if(peticio_http.readyState == READY_STATE_COMPLETE) {if(peticio_http.status == 200) {alert(peticio_http.responseText);}}}Per últim, la funció descarregaArxiu() simplement realitza una crida a la funciócarregaContingut() amb els paràmetres adequats:function descarregaArxiu() {carregaContingut("http://localhost/prova2.txt", "GET", mostraContingut);}A continuació es mostra el codi complet de la refactorització de la primera aplicació:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head><title>Prova desde Ajax</title><script type="text/javascript" language="javascript">var READY_STATE_UNINITIALIZED=0;var READY_STATE_LOADING=1;var READY_STATE_LOADED=2;var READY_STATE_INTERACTIVE=3;
  7. 7. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/var READY_STATE_COMPLETE=4;var peticio_http;function carregaContingut(url, metode, funcio) {peticio_http = inicialitza_xhr();if(peticio_http) {peticio_http.onreadystatechange = funcio;peticio_http.open(metode, url, true);peticio_http.send(null);}}function inicialitza_xhr() {if(window.XMLHttpRequest) {return new XMLHttpRequest();}else if(window.ActiveXObject) {return new ActiveXObject("Microsoft.XMLHTTP");}}function mostraContingut() {if(peticio_http.readyState == READY_STATE_COMPLETE) {if(peticio_http.status == 200) {alert(peticio_http.responseText);
  8. 8. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/}}}function descarregaArxiu() {carregaContingut("http://localhost/prova2.txt", "GET", mostraContingut);}window.onload = descarregaArxiu;</script></head><body></body></html>Utilitats i objectes per a AjaxUna de les operacions més habituals en les aplicacions Ajax és la dobtenir el contingut dunarxiu o recurs del servidor. Per tant, construirem un objecte que permeti realitzar la càrrega dedades del servidor simplement indicant el recurs sol·licitat i la funció encarregada de processarla resposta:var carregador = new net.CarregadorContingutss("pagina.html", processaResposta);La lògica comuna dAjax sencapsula en un objecte de manera que sigui fàcilment reutilitzable.Aplicant els conceptes dobjectes de Javascript, funcios constructores i lús de prototype, éspossible realitzar de forma senzilla lobjecte carregador de continguts:var net = new Object();net.READY_STATE_UNINITIALIZED=0;net.READY_STATE_LOADING=1;
  9. 9. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/net.READY_STATE_LOADED=2;net.READY_STATE_INTERACTIVE=3;net.READY_STATE_COMPLETE=4;// Constructornet.CarregadorContinguts = function(url, funcio, funcioError) {this.url = url;this.req = null;this.onload = funcio;this.onerror = (funcioError) ? funcioError : this.defaultError;this.carregaContingutXML(url);}net.CarregadorContinguts.prototype = {carregaContingutXML: function(url) {if(window.XMLHttpRequest) {this.req = new XMLHttpRequest();}else if(window.ActiveXObject) {this.req = new ActiveXObject("Microsoft.XMLHTTP");}if(this.req) {try {var loader = this;this.req.onreadystatechange = function() {loader.onReadyState.call(loader);
  10. 10. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/}this.req.open(GET, url, true);this.req.send(null);} catch(err) {this.onerror.call(this);}}},onReadyState: function() {var req = this.req;var ready = req.readyState;if(ready == net.READY_STATE_COMPLETE) {var httpStatus = req.status;if(httpStatus == 200 || httpStatus == 0) {this.onload.call(this);}else {this.onerror.call(this);}}},defaultError: function() {alert("S’ha produït un error l’obtenir les dades"+ "nnreadyState:" + this.req.readyState+ "nstatus: " + this.req.status
  11. 11. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/+ "nheaders: " + this.req.getAllResponseHeaders());}}Una vegada definit l’objecte net amb el seu mètode CarregadorContinguts(), ja és possibleutilitzar-ho en las funcioes que s’encarreguen de mostrar el contingut de l’arxiu del servidor:function mostraContingut() {alert(this.req.responseText);}function carregaContinguts() {var cargador = new net.CarregadorContinguts("http://localhost/prova2.txt",mostraContingut);}window.onload = carregaContinguts;En l’exemple anterior, l’aplicació mostra un missatge amb els continguts de la URL indicada:Missatge mostrat quan el resultat és exitós.Missatge mostrat quan el resultat és reeixitDaltra banda, si la URL que es vol carregar no és vàlida o el servidor no respon, laplicaciómostra el següent missatge derror:Missatge mostrat quan el resultat és erroni.Missatge mostrat quan el resultat és erroniEl codi del carregador de continguts fa un ús intensiu dobjectes, JSON, funcios anònimes i úsde lobjecte this. Seguidament, es detalla el funcioament de cadascuna de les seves parts.
  12. 12. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/El primer element important del codi font és la definició de lobjecte net.var net = new Object();Es tracta duna variable global que encapsula totes les propietats i mètodes relatius a lesoperacions relacionades amb les comunicacions per xarxa. En certa manera, aquesta variableglobal simula el funcioament dels namespaces ja que evita la col·lisió entre noms de propietatsi mètodes diferents.Després de definir les constants emprades per lobjecte XMLHttpRequest, es defineix elconstructor de lobjecte CarregadorContinguts:net.CarregadorContinguts = function(url, funcio, funcioError) {this.url = url;this.req = null;this.onload = funcio;this.onerror = (funcioError) ? funcioError : this.defaultError;this.carregaContingutXML(url);}Encara que el constructor defineix tres paràmetres diferents, en realitat només els dos primerssón obligatoris. Daquesta forma, sinicialitza el valor dalgunes variables de lobjecte, escomprova si sha definit la funció que sempra en cas derror (si no sha definit, sempra unafunció genèrica definida més endavant) i sinvoca el mètode responsable de carregar el recurssol·licitat (carregaContingutXML).net.CarregadorContinguts.prototype = {carregaContingutXML:function(url) {...},onReadyState:function() {...},defaultError:function() {...}}
  13. 13. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/Els mètodes emprats per lobjecte net.carregaContinguts es defineixen mitjançant el seuprototip. En aquest cas, es defineixen tres mètodes diferents: carregaContingutXML() percarregar recursos de servidor, onReadyState() que és la funció que sinvoca quan es rep laresposta del servidor i defaultError() que és la funció que sempra quan no sha definit deforma explícita una funció responsable de gestionar els possibles errors que es produeixin enla petició HTTP.La funció defaultError() mostra un missatge davís de lerror produït i a més mostra el valordalgunes de les propietats de la petició HTTP:defaultError:function() {alert("S’ha produït un error al obtenir les dades"+ "nnreadyState:" + this.req.readyState+ "nstatus: " + this.req.status+ "nheaders: " + this.req.getAllResponseHeaders());}En aquest cas, l’objecte this es resol a l’objecte net.carregaContinguts, ja que és l’objecte queconté la funció anònima que s’està executant.D’altra banda, la funció onReadyState és l’encarregada de gestionar la resposta del servidor:onReadyState: function() {var req = this.req;var ready = req.readyState;if(ready == net.READY_STATE_COMPLETE) {var httpStatus = req.status;if(httpStatus == 200 || httpStatus == 0) {this.onload.call(this);} else {this.onerror.call(this);}
  14. 14. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/}}Després de comprovar que la resposta del servidor està disponible i és correcta, es realitza lacrida a la funció que realment processa la resposta del servidor dacord a les necessitats delaplicació.this.onload.call(this);Lobjecte this es resol com net.CarregadorContinguts, ja que és lobjecte que conté la funcióque sestà executant. Per tant, this.onload és la referència a la funció que sha definit com aresponsable de processar la resposta del servidor (es tracta duna referència a una funcióexterna).Normalment, la funció externa encarregada de processar la resposta del servidor, requeriràaccedir a lobjecte XMLHttpRequest que emmagatzema la petició realitzada al servidor. En unaltre cas, la funció externa no serà capaç daccedir al contingut retornat pel servidor.Com ja hem vist anteriorment, el mètode call() és un dels mètodes definits per a lobjecteFunction(), i per tant disponible per totes les funcions de Javascript. Emprant el mètode call()és possible obligar a una funció a ser executada sobre un objecte concret. En altres paraules,emprant el mètode call() sobre una funció, és possible que dins daquesta funció lobjecte thises resolgui com lobjecte passat com a paràmetre en el mètode call().Així, la instrucció this.onload.call(this); sinterpreta de la següent forma:Lobjecte this que es passa com a paràmetre de call() es resol com lobjectenet.CarregadorContinguts.Lobjecte this.onload emmagatzema una referència a la funció externa que es va a emprar perprocessar la resposta.El mètode this.onload.call() executa la funció, la referència de la qual, semmagatzema enthis.onload.La instrucció this.onload.call(this); permet executar la funció externa amb lobjectenet.CarregadorContinguts accessible a linterior de la funció mitjançant lobjecte this.Finalment, el mètode carregaContingutXML sencarrega denviar la petició HTTP i realitzar latrucada a la funció que processa la resposta:carregaContingutXML:function(url) {if(window.XMLHttpRequest) {this.req = new XMLHttpRequest();}else if(window.ActiveXObject) {
  15. 15. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/this.req = new ActiveXObject("Microsoft.XMLHTTP");}if(this.req) {try {var loader=this;this.req.onreadystatechange = function() {loader.onReadyState.call(loader);}this.req.open(GET, url, true);this.req.send(null);} catch(err) {this.onerror.call(this);}}}En primer lloc, sobté una instància de lobjecte XMLHttpRequest en funció del tipus denavegador. Si sha obtingut correctament la instància, sexecuten les instruccions mésimportants del mètode carregaContingutXML:var loader = this;this.req.onreadystatechange = function() {loader.onReadyState.call(loader);}this.req.open(GET, url, true);this.req.send(null);A continuació, semmagatzema la instància de lobjecte actual (this) en la nova variable loader.Una vegada emmagatzemada la instància de lobjecte net.CarregadorContinguts, es defineix lafunció encarregada de processar la resposta del servidor. En la següent funció anònima:
  16. 16. Más manuales en: http://www.exabyteinformatica.com/manuales-y-apuntes-freeware© Roger Casadejús Pérez | http://www.exabyteinformatica.com/tienda/this.req.onreadystatechange = function() { ... }A linterior daquesta funció, lobjecte this no es resol en lobjecte net.CarregadorContinguts,per la qual cosa no es pot emprar la següent instrucció:this.req.onreadystatechange = function() {this.onReadyState.call(loader);}No obstant això, des de linterior daquesta funció anònima si és possible accedir a les variablesdefinides en la funció exterior que lengloba. Així, des de linterior de la funció anònima sí queés possible accedir a la instància de lobjecte net.CarregadorContinguts que es vaemmagatzemar anteriorment.En el codi anterior, no és obligatori emprar la crida al mètode call(). Es podria haver definit dela següent forma:var loader=this;this.req.onreadystatechange = function() {// loader.onReadyState.call(loader);loader.onReadyState();}A linterior de la funció onReadyState, lobjecte this es resol com net.ContentLoader, ja que estracta dun mètode definit en el prototip del propi objecte.

×