Tenía curiosidad al respecto de esa nueva tecnología que llaman COMET y que básicamente consiste en mantener una comunicación constante entre el cliente y el servidor web. Para explorar un poco, me planteé un proyecto sencillo: un chat asíncrono web.
La estructura es la siguiente:
Los principales problemas de esta aproximación son los siguientes:
Veamos un poco de código. Lo siguiente sería el html del chat, muy sencillo y que no necesita explicación (creo).
1 <html> 2 <head> 3 <script language="javascript" src="chat.js"></script> 4 <title>Chat con eventos compartidos en servidor COMET</title> 5 </head> 6 <body onload="javascript: main()"> 7 <textarea id="chatPanel" rows="10" cols="90" disabled="true"></textarea> 8 <input type="text" id="nick" disabled="true"/> 9 <form onsubmit="javascript:return send();"> 10 <input type="text" id="chatBox" value="" style="width:90%"/> 11 </form> 12 </body> 13 </html>
Como veis, lo único que hacemos es traernos un archivo js (chat.js) y definirnos un par de campos para presentar datos. El campo 'chatBox' llama a una función llamada 'send()' para enviar al servidor lo que se escriba en él.
Una cosa más, en el onload llamamos a una función 'main()' que veremos a continuación.
1 var nick = ""; 2 var x; 3 var x_Send; 4 var intervalo; 5 var last_id=0; 6 7 function main(){ 8 while(nick == "") nick = prompt("Nick:"); 9 document.getElementById("nick").value=nick; 10 openStream(); 11 } 12 function openStream(){ 13 x = new XMLHttpRequest() 14 x.open("GET", "chatServer.php?accion=listen", true); 15 x.send(null); 16 intervalo = setInterval(poll, 1000); 17 } 18 function closeStream(){ 19 clearInterval( intervalo ); 20 x.abort(); 21 openStream(); 22 } 23 function poll(){ 24 var r = new Array(); 25 r= x.responseText.split("\n"); 26 for(var f=0; f< r.length; f++){ 27 if(r[f]=="") continue; 28 var evento = eval("("+ r[f] + ")" ); 29 if(evento.id> last_id){ 30 last_id = evento.id; 31 echo(evento.nick+": "+evento.msg+"\n"); 32 } 33 } 34 if(x.readyState == 4) closeStream(); 35 } 36 function echo( str ){ 37 document.getElementById("chatPanel").value += str; 38 document.getElementById("chatPanel").scrollTop = document.getElementById("chatPanel").scrollHeight; 39 } 40 function send(){ 41 x_Send = new XMLHttpRequest(); 42 var msg = document.getElementById("chatBox").value; 43 x_Send.open("GET", "chatServer.php?accion=send&msg="+msg+"&who="+nick, true); 44 x_Send.send(null); 45 document.getElementById("chatBox").value = ""; 46 return false; 47 }
Aquí si que hay jugo. Vamos función por función.
main(): Nos pide un 'nick' y llama a openStream().
openStream(): Abre una petición XMLHttpRequest al archivo chatServer.php con el código de acción 'listen' que como veremos posteriormente, indica al php que se quede en espera y nos vaya enviando mensajes. ¿Cuando leemos esos mensajes? pues para ello nos definimos un intervalo cada segundo (podría ser menos si necesitamos mñas interactividad) para que llame a la función 'poll()'.
closeStream(): Cierra la petición XMLHttpRequest y vuelve a crear otra llamando a openStream.
poll():Esta función recoge el contenido actual del responseText de la petición de escucha, la divide en lineas y si corresponde, imprime la línea por pantalla con 'echo()'.
echo(): Escribe lo que le mandes como parametro en el textarea y mueve el scroll.
send(): Envía el texto al servidor mediante un XMLHttpRequest normalito.
Hasta aquí la parte del cliente. Hemos visto como implementar mediante javascript hilos de escucha con el servidor. ¿Utilidad? Para todas aquellas aplicaciones en la que la colaboración entre usuarios es fundamental o crítica. Se me ocurre, a bote pronto, edición multiusuario de documentos online, control de concurrencia, etc...
Mientras escribo la segunda parte de este mini tutorial, podeis entreteneros probando el chat en la siguiente url: chat web. Eso si, si solo estás tú conectado, no vas a ver nada espectacular. Lo suyo es probarlo con muchos usuarios.
Actualización: Ya tengo lista la segunda parte.
Artículo escrito por Francisco Javier Nieto Borrallo.