Introducción a Javascript
JJ Merelo
[email protected] [email protected]
1ª edición
A José Antonio Vacas, mis alumnos de AAP, los alumnos del curso virtual, y todo el que ha echado una mano corrigiendo errores y comentando esto, empezando por Marcos Taracido.
Índice
Índice de contenido ¿Javascript? Pero si es muy fácil ....................8 Primer programa en Javascript.................... 12 Estructuras de control ................................. 1 !lases y o"#etos en Javascript...................... 18 $atrices asociativas .................................... 2 $ane#ando %"#etos .....................................2& %"#etos para el camino ............................... ' (unciones como o"#etos ............................. )1 !ommonJ*+ una infraestructura com,n para carga de módulos........................................ )8 Para finali-ar................................................ / 0gradecimientos.......................................... 1 i"liografa................................................... 1 El modelo de o"#etos................................... 2 3sando 4rease$on5ey................................ 61 7ra"a#ando con otras ventanas................... 66
*electores.................................................... 68 Eventos........................................................68 Juery9 :ntroducción....................................'/ ;ode.#s+ un int
E*7 ...................... &2 El protocolo 77P y sus m,ltiples posi"ilidades .................................................................... & :nterfaces >E*7 simples con e@press......... 1/ !lientes >E*7............................................. 1/' 3sando 0#[email protected]/& $ás allá del 0#a@ ....................................... 116 0 dónde ir desde aAu ................................ 11' i"liografa y enlaces................................. 118
Introducción al lenguaje de programación Javascript 0prender Au< es Javascript 0prender la sinta@is de Javascript 3sar o"#etos y clases en Javascript >eali-ar un peAueBo e#emplo en Javascript
• • • •
¿Javascript? Pero si es muy fácil (uera de ser solamente un lengua#e para el navegador+ Javascript tiene una venta#a frente a otros lengua#es de programación9 Está en todas partes. ;o Cay ordenador sin navegador+ ni Cay navegador sin Javascript Dsalvo en móviles y algunos P0sF. *e puede e#ecutar Casta en el navegador %pera Aue viene con la GiiH desde la madure- de node.#s+ es el ,nico lengua#e Aue permite e#ecutar aplicaciones en cliente y servidor+ as Aue se Ca convertido en uno de los lengua#es más ,tiles para desarrollo en :nternet. Esto se de"e+ en parte a Aue Ca sido definido como un estándar E!$0 Ddenominado E!$0*criptF lo Aue da lugar a mucCas implementaciones diferentes+ Aue son+ además+ independientes del fa"ricante. I+ por otro lado+ tam"i
pueden usar para aBadir funcionalidad a una aplicación. $ucCas aplicaciones comple#as+ como 4$ail o 4oogle docs dependen de estos o"#etos para crear aplicaciones en la =e" Aue se comporten como si se e#ecutaran en un sistema operativo nativoH a estas aplicaciones se les Ca denominado ,ltimamente Rich nternet Applications. 0demás+ a diferencia de otros lengua#es+ es muy fácil crear una aplicación distri"uida con Javascript. 7anto por su integración con el navegador Dparte insepara"le de la =e"+ una arAuitectura clienteservidorF como por los o"#etos Aue suele tener el mismo+ crear una aplicación clienteservidor es casi trivial y Ca dado lugar a un estilo de programación denominado 0J0K+ Aue se verá más adelante en esta misma asignatura. Para e#ecutar Javascript no Cace falta más Aue un navegador+ pero tam"iCino+
;ormalmente está activado por omisión. Por otro lado+ veremos e#emplos principalmente de programas Aue se pueden usar desde el int
Por lo Aue Ce pro"ado+ *pider$on5ey+ >Cino y NJ*!$ se instalan fácilmente en 3"untuH no Cay más Aue Cacer aptitude search javascript Den u"untuF y salen esos y alguno más. (edora !ore es un poco más rácano en cuanto a entornos9 aunAue los puedes instalar "a#ándote los fuentes y compilando+ el Aue está disponi"le en los repositorios es uno llamado sólo js+ aparentemente el *pider$on5ey. Para instalarlo+ escri"ir yum install js. Para los e#emplos Aue vienen en este tema+ sustituir #!/usr/bin/smjs por #!/usr/bin/js. El 4nome *Cell Dincluido en la versión ./ de 4nomeF incluye tam"i
7am"i
Primer programa en Javascript
QRusr"insm#s printD Sola+ $undoS FH En realidad+ el J* es "astante parecido al !+ y+ para el caso+ tam"i
#mereloTvega9Ut@tdocencia00P7em arioV code#sCola.#s ola+ $undo Para e#ecutarlo desde el navegador Ca"rá Aue Cacer una poca más de Cistoria+ pero tampoco tanto. Wo vemos en este e#emplo Ddarle a ver fuente para ver el códigoF donde se incluye el programa en J* de esta forma9
Xscript typeYSte@t#avascriptS srcYSCola.#sSMXscriptM El pro"lema es Aue+ en este caso+ la orden print se interpreta como impresión por impresora+ y Ca"rá Aue cam"iarla por otra Aue signifiAue lo mismo+ escri"ir en el dispositivo de salida Aue se est< usando9
document.=ritelnDSola+ $undoSF Wo Aue tam"i
Xscript typeYSte@t#avascriptSM
document.=ritelnDSola+$undoSF XscriptM Estos programas se pueden usar con cualAuier editor de te@to+ Emacs+ *u"lime 7e@t o ;otepadZ ZH tam"i
Estructuras de control [istas ya las mil y una formas de escri"ir cosas en la pantalla+ procedamos a temas más esca"rosos+ como lo Aue viene siendo Cacer algo realmente. Por e#emplo+ un "ucle Aue cree una ta"la 7$W+ como se Cace en el siguiente programilla9
var ta"laY\ta"le\H var celdaY\td\H var filaY\tr\H var matri- Y ]1+2+^H printD \X\Zta"laZ\M\FH for Di in matri- F _ printD \X\ZfilaZ\M\FH for D # in matri- F _ printD\X\ZceldaZ\M\ Zmatri-]i^`matri-]#^ Z\X\ZceldaZ\M\FH
print D\X\ZfilaZ\Mbn\FH print D\X\Zta"laZ\M\FH Este programa tiene dos "ucles anidados+ Aue imprimen un producto dentro de una ta"la. Wa salida será tal Aue as Dver el fuente para la estructuraF9 1 2 2 ) 6 6 & El programa es menos complicado de lo Aue parece. Para declarar varia"les en J* se usa el gen
y se pueden usar igual Aue en !+ pero Caremos un "ucle Aue recorra la matri-+ usando un iterador i+ Aue en este caso se comporta como una varia"le de "ucle de las de toda la vida. 3samos el + para concatenación de cadenas+ y poco más. El resto es como el !+ o el Java. e CecCo+ se pueden usar los "ucles clásicos con comparación e incremento+ como se muestra en ta"la1.#s9
for DiY1H iXYH iZZ _ printD \X\ZfilaZ\M\FH for D #Y1H #XYH #ZZ F _ printD\X\ZceldaZ\M\ Zi`# Z\X\ZceldaZ\M\FH print D\X\ZfilaZ\Mbn\FH 0unAue Aueda un poco torpe tanto XM... vamos a reducir un poco el programa+ Caci
var matri- Y ]1+2+^H printD marcaDSta"leSFFH for Di in matri- F _
printD marcaD StrS FFH for D # in matri- F _ printD celdaDmatri-]i^`matri-]#^FFH print D finmarcaDStrSFFH print DfinmarcaDSta"leSFFH function marcaD m F _ return \X\ZmZ\M\H function finmarcaD m F _ return \X\ZmZ\M\H function celdaD contenido F _ return marcaD\td\F Zcontenido ZfinmarcaD\td\FH
Wa principal diferencia con respecto al anterior es el uso de funciones. Was funciones en J* tienen una estructura "astante clásica9 function nom"redefunción Dparam1+ param2...F. 3na vemás+ se nota Aue J* no e un lengua#e con tipos fuertes+ pudiendo pasar los parámetros sin tipo+ y adaptándose dentro de la función al tipo necesario. *e pasan por valor+ es decir+ Aue las modificaciones al parámetro formal no se trasladan a la varia"le Aue se use. 0demás+ se pueden declarar donde a uno le d< la gana. Para llamarlas tampoco Cay Aue Cacer nada especial+ se usa el clásico par
Clases y objetos en Javascript Javascript es un lengua#e "asado en o"#etos+ aunAue un tanto peculiarH en realidad+ de casi todas las caractersticas de un lengua#e orientado a o"#etos+ solo tiene los o"#etos+ e incluso estos son un tanto peculiares. Por eso no es e@actamente dirigido a o#$etos u orientado a o#$etos. Was caractersticas las veremos en el siguiente programa+ Aue podra servir para Cacer Auinielas.
var eAuiposY ne= 0rrayDS$adridS+ SaraS+ S0tletiS+ S4etaS+ SetisS+ SeporS+ S*evillaS+ S4ranáSFH efinición de la clase Partido function PartidoDlocal+visitanteF_ tCis.local Y localH tCis.visitanteYvisitanteH tCis.resultadoYnullH var midsi-e Y eAuipos.lengtC2H var Auiniela Y ne= 0rrayD midsi-e FH for D iY/H i X midsi-e H iZZ F _
var eAuipo1 Y eAuipos.spliceD$atC.floorD eAuipos.lengtC`$atC.randomDFF + 1FH var eAuipo2 Y eAuipos.spliceD$atC.floorD eAuipos.lengt C`$atC.randomDFF+ 1FH Auiniela]i^ Y ne= PartidoD eAuipo1+ eAuipo2 FH for D i in Auiniela F _ printD \Partido \ Z Dparse:ntDiFZ1F Z\9 \ Z Auiniela]i^.local Z \ \ Z Auiniela]i^.visitanteFH !on lo primero Aue nos enfrentamos es con una nueva forma de definir una matri- o Array9 ya Aue sa"emos Aue J* es %%+ pues usamos una forma %% de definirlo+ mediante la orden ne+ Aue+ como en Java y en !ZZ+ crea un nuevo o"#eto llamando al constructor del mismo. En este caso le pasamos
directamente los elementos Aue constituyen el vector o array + pero podramos Ca"erle pasado el tamaBo de esta forma9 var my0rray Y ne= 0rrayDFH Wos o"#etos as creados son o"#etos de pleno derecCo+ y se puede acceder a sus propiedades con m
d< por saco mientras generamos el resto de la guiniela. I el o"#eto lo creamos mediante una clásica llamada9
Auiniela]i^ Y ne= PartidoD eAuipo1+ eAuipo2 FH $ás adelante usamos un "ucle in para escri"ir los valores de cada uno de los partidosH las varia"les no están encapsuladas+ as Aue se puede acceder a ellas directamente9 partidolocal+ por e#emplo. ay tam"i
Partido /9 4raná 0tleti Partido 19 $adrid epor Partido 29 etis ara Partido 9 *evilla 4eta 0Badir m
efinición de la clase Partido function PartidoDlocal+visitanteF_ tCis.local Y localH tCis.visitanteYvisitanteH tCis.resultadoYnullH tCis.set>esultado Y set>esultadoH tCis.to*tring Y to*tringH function set>esultadoD este>esultado F_ if D este>esultado YY S1S este>esultadoYYS@S este>esultadoYYS2S F tCis.resultado Y este>esultadoH function to*tringDF _ return \Partido \ Z i Z \9 \ Z tCis.local Z \ \ Z tCis.visitante Z \ Y \Z tCis.resultadoH
0Badimos un par de funciones+ y para Aue pertenezcan a la clase+ Cala+ con un this por aAu y un this por allá+ solucionado. Es de "uen gusto llamar al m
Matrices asociativas Pero Cay más matrices+ aparte de las lineales9 J*+ como mucCos otros lengua#es+ permite tra"a#ar con matrices asociativas Dtam"i
so"re sus valores+ por e#emploF sólo se usan sus valores9 valor]/^+ valor]1^+...+ valor]n^. *in em"argo+ una matri- asociativa+ diccionario+ mapa o 7a"laCasC Do simplemente hashF está compuesto por una serie de pares Dcadena alfanum
Q L para matrices asociativas my Lmatri-0sociativaH Q _ para las claves Vmatri-0sociativa_Svaria"leSYS[alorSH print Vmatri-0sociativa_Svaria"leSH devolvera Valor. Was usaremos en el siguiente programa+ Aue genera aleatoriamente die- #ornadas de una liga+ y asigna puntuación seg,n los resultados9
loadDSPartido.#sSFH
var eAuiposY ne= 0rrayDS$adridS+ SaraS+ S0tletiS+ S4etaS+ SetisS+ SeporS+ S*evillaS+ S4ranáSFH function #ornadaD estosEAuipos F _ var eAuipos0Aui Y ne= 0rrayH eAuipos0Aui Y eAuipos0Aui.concatDestosEAuiposFH var midsi-e Y eAuipos0Aui.lengtC2H var Auiniela Y ne= 0rrayD midsi-e FH var uno@2 Y ne= 0rrayD S1S+S@S+S2SFH for D var iY/H i X midsi-e H iZZ F _ var eAuipo1 Y eAuipos0Aui.spliceD$atC.floorD eAuipos0 Aui.lengtC`$atC.randomDFF + 1FH var eAuipo2 Y eAuipos0Aui.spliceD$atC.floorD eAuipos0 Aui.lengtC`$atC.randomDFF+ 1FH Auiniela]i^ Y
ne= PartidoD eAuipo1+ eAuipo2 FH Auiniela]i^.set>esultadoD uno@2]$atC.flo orD `$atC.randomDFF ^FH return AuinielaH var Auinielas Y ne= 0rrayH for D var i Y /H i X 1/H i ZZ F_ Auinielas]i^ Y #ornadaD eAuipos FH var resultadosY ne= 0rrayH for D var i in eAuipos F_ resultados]eAuipos]i^^Y/H for D var i Y /H i X Auinielas.lengtCH i ZZ F_ for D var # Y /H # X Auinielas]i^.lengtCH # ZZ F _
var local Y Auinielas]i^ ]#^.localH var visitante Y Auinielas]i^ ]#^.visitanteH var resultado Y Auinielas]i^ ]#^.resultadoH if D resultado YY 1 F_ resultados]local^ZYH else if D resultado YY S@S F_ resultados]local^ZY1H resultados]visitante^ ZY1H else _ resultado YY 2 resultados]visitante^ ZY for D var i in resultados F _ printD i Z \9 \ Z resultados]i^F
En parte+ este programa es similar a los anteriores9 la parte Aue genera"a cada #ornada está aCora en una función+ Aue devuelve un array de resultados+ Aue se guardan en el array (uinielas. emos sacado+ además+ la definición de la clase "artido a un ficCero e@terno+ Aue cargamos con load. Por otro lado+ como a la función jornada se le pasa una referencia al vector con los eAuipos+ tenemos Aue copiarlo a una varia"le local+ defini
resultados]eAuipos]i^^Y/H e(uipos)i* valdrá sucesivamente ara+ 4raná... y as se irán iniciali-ando a / los valores correspondientes. *i no se iniciali-an+ la primera ve- Aue se usa una varia"le tiene el valor a+ con el Aue no se puede Cacer nada. Es as de arisco. $ás adelante se va recorriendo en un "ucle do"le los partidos de cada una de las #ornadas+ y asignando puntuación dependiendo del resultado de la Auiniela. *e usa la construcción if else if else+ Aue funciona de la forma Ca"itual+
aunAue tam"i
s=itcC DresultadoF _ case S1S9 resultados]local^ZYH "rea5H case S@S9 resultados]local^ZY1H resultados]visitante^ZY1H "rea5H default9 resultados]visitante^ZYH y Aue viene a ser como el anterior+ pero con cases en ve- de ifs. [amos+ tres cuartos de lo mismo.
Manejando bjetos En realidad+ todo en Javascript es un o"#eto+ y especialmente los vectores9 tanto los vectores tradicionales como las matrices asociativas como los o"#etos se representan internamente de la
misma forma+ y te puedes referir a ellos de diferentes maneras. [amos a usar el depurador interactivo para verlo+ e#ecutando simplemente rhino+ smjs o ,js en la lnea de comandos. 3na ve- CecCo+ tecleamos las siguientes órdenes9 js> foo = new Array js> foo.cero=!ero
!ero js> foo"#$ = %no
3no js> foo"dos$ = &os
os js> foo.dos
os js> foo"cero$
!ero js> for ' i in foo( ) print'foo"i$(*+
!ero 3no os ay Aue teclear lo Aue se encuentra detrás de js-H cada segunda lnea es la respuesta del int
asociativa para el 2. Wuego se ve Aue+ independientemente de cómo se Caya asignado el valor+ se puede usar cualAuier otra notación para acceder al elementoH y+ finalmente+ vemos como se puede recorrer de forma uniforme el array usando sus componentes mediante la orden in. Por eso precisamente+ Cay Aue tener un poco de cuidado con estos arrays asociativos Aue se comportan un poco como les da la gana. Es conveniente usar para ellos .bject+ Aue es lo Aue son+ en ve- de Array. e CecCo+ si en lo anterior sustituimos Array por .bject dará e@actamente el mismo resultado. Por eso se consideran perniciosas los arrays asociativos en J*+ pero es simplemente una cuestión de convención. ;o todo va a ser p,"lico en un o"#etoH tam"i function ,oo' -ar ( ) tis.-ar = -ar* var privada = /*+ js> var este0foo = new ,oo' corre1uetepillo (* js> print'este0foo.-ar(
correAuetepillo js> print'este0foo.privada(
undefined
Es tan secreta+ de CecCo+ Aue ni siAuiera te dice Aue no e@iste9 simplemente Aue su valor está indefinido. El propio estándard Javascript DE!$0*criptF define una serie de clases Aue se pueden instanciar+ Aue corresponderan a la li"rera estándar Do li"rera estándar de clasesF en otros lengua#es. 3na de ellas ya la Cemos visto9 la clase Array. %tra es la clase tring+ Aue se usa para mane#ar cadenas alfanum var cadena = new 2tring'3#3(* js> print'cadena 4 #(
11 Wa clase tring tiene una serie de m var nom-res = 35edro6 7ucas6 Juan3.split'36 3(* js> print'nom-res"8$(
Pedro En este caso+ split es un m
todava no Cemos visto ninguna+ y+ además+ cualAuier lengua#e decente escri"e y lee ficCeros. Es más+ es Aue mucCos no Cacen otra cosa+ ¿no? Pues no. El estándar J* no define ning,n tipo de rutina de E*. Pero si usamos el intCino Den ve- de *pider$on5ey+ Aue es el Aue Cemos venido usandoF+ podemos usar clases de Java directamente+ lo Aue complica terri"lemente el programa+ pero aC está+ de todas formas9
e#ecutar con rCino leeAuiniela.#s XargumentoM loadDSPartido.#sSFH var (ile>eader Y #ava.io.(ile>eaderH var uffered>eader Y#ava.io.uffered>eaderH var filename Y arguments]/^H var f Y ne= (ile>eaderDfilenameFH var "r Y ne= uffered>eaderD f FH var resultadosY ne= 0rrayH var line Y ne= *tringH =Cile DDline Y "r.readWineDFF RY nullF_ var estaWinea Y ne= *tringD line FH
var resultado Y estaWinea.splitD\ \FH s=itcC Dresultado]2^F _ case S1S9 if D resultados]resultado]/^^ F _ resultados]resultado]/^^ZYH else _ resultados]resultado]/^^YH "rea5H case S@S9 if D resultados]resultado]/^^ F _ resultados]resultado]/^^ZY1H else _ resultados]resultado]/^^Y1H if D resultados]resultado]1^^ F _ resultados]resultado]1^^ZY1H else _ resultados]resultado]1^^Y1H
"rea5H default9 if D resultados]resultado]1^^ F _ resultados]resultado]1^^ZYH else _ resultados]resultado]1^^YH "rea5 for D var i in resultados F _ printD i Z \9 \ Z resultados]i^F El programa es "astante similar al anterior+ pero lee de ficCero en ve- de generar los resultados aleatoriamente. I lo lee apro@imadamente de la misma forma a como se Cara en Java. Por eso Cay Aue usar >Cino+ Aue permite usar las clases de la li"rera estándar de Java de forma nativa. En este caso usamos dos clases9 4ile5eader y 6uffered5eader+ para poder leer de lnea en lnea. Wa ,nica diferencia a como se Cara en Java es Aue Cay Aue pasar la lnea leida de un o"#eto tring de Java a un o"#eto tring de J*+ Aue es lo Aue se
Cace en var esta2inea 7 ne tring& line '8. 7am"i
ElcCe9 1 0tleti9 !ai9 1 0tCleti9 6 arUa9 1 $adrid9 2 Urcules9 1 ueda con esto más o menos claro Aue para ir donde nadie Ca ido antes con J*+ Cay Aue meterse un poco en Java. Pero no siempre. 7en
nom"res completos e incluso como implementar intervaces de Java. 0unAue no lo pare-ca+ J* es todava un lengua#e #oven+ al Aue le faltan gran cantidad de li"reras "ásicas+ y+ especialmente+ una forma centrali-ada de empaAuetar+ pro"ar y distri"uir esas li"reras+ como !P0; para Perl o 4E$s para >u"y. ay algo por el estilo+ llamado %penJ*0;+ de J* 0rcCive ;et=or5. Para instalarlo Cace falta Perl+ y sólo Cay unas pocas li"reras todava. 0lgunas muy ,tiles+ pero siguen siendo unas pocas. %tras+ como la amplia J*li"+ sólo va en Gindo=s. En todo caso+ a estas alturas parece un proyecto muerto y en realidad las ,nicas li"reras Aue se usan con asiduidad y facilidad son las de ;ode+ Aue veremos más adelante. Wa Aue si es popular es Prototype+ una li"rera Aue se usa principalmente en con#unción con >o> y 0J0K+ pero resulta Aue necesita e#ecutarse dentro del navegador+ porAue usa o"#etos del mismo Dcomo document+ por e#emploF. 0s Aue la de#aremos para más adelante.
bjetos para el camino Wo interesante de los o"#etos en J* es Aue Cay una forma muy fácil de serializarlos Des decir+ convertirlos en te@to u otro formato de forma Aue se puedan intercam"iar fácilmente con otros programas a trav
apartado anterior+ todo es un o"#eto en J*+ se puede usar esta notación para asignar valores prácticamente a cualAuier cosa. [amos a usar una ve- más el int var o-jeto = ) Madrid 9 :;6 Atleti9 <<6 5onferradina9 +* js> for 'i in o-jeto( ) print' i 4 3 9 34 o-jeto"i$ (+*
$adrid 9 2 0tleti 9 Ponferradina 9 )) $ás fácil no puede ser. *e le asigna valor a un o"#eto con el formato clave 9 valor Dcon coma al finalF+ de la misma forma Aue se Cara a un array asociativo. 0demás+ se pueden crear o"#etos so"re la marcCa y asignárselos a una varia"le cuyo valor se cree tam"i eval'3var o-jeto: = ) Madrid 9 :;6 Atleti9 <<6 5onferradina9 +3(* js> for 'i in o-jeto:( ) print' i 4 3 9 34 o-jeto"i$ (+*
$adrid 9 2 0tleti 9 Ponferradina 9 )) donde usamos eval+ Aue interpreta una e@presión en Javascript como si del propio int
js> eval'3var o-jeto: = ) Madrid 9 :;6 Atleti9 <<6 5onferradina9 ) casa9 <<6 fuera9 + +3(* js> for 'i in o-jeto:( ) print' i 4 3 9 34 o-jeto:"i$ (+*
$adrid 9 2 0tleti 9 Ponferradina 9 ]o"#ect %"#ect^ ue parece más raro de la cuenta+ pero Aue+ con un poco de código+ se podra tam"i
getWocationD#ataF _ if D#ata YY nullF _ returnH var Ctml Y SXulMSH var geonames Y #ata.geonamesH for DiY/HiXgeonames.lengtCHiZZF _ var name Y geonames]i^H
Ctml Y CtmlZ\XliMXemM\ Zname.name Z \XemM Watitud9 \ Z name.lat ZS+ longitud9 S Z name.lngZ \XliM\H CtmlZY\XulM\H document .getElementy:dDSresultivSF .inner7$W Y CtmlH function searcCDF _ reAuest Y SCttp9=s.geonames.orgsearcCJ*%;? countryYE*AYS Z encode3>:!omponentDdocument.getEle menty:dDSASF.valueF Z Sma@>o=sY1/call"ac5YgetWocationSH a%"# Y ne= J*%;script>eAuestDreAuestFH a%"#."uild*cript7agDFH
a%"#.add*cript7agDFH Este e#emplo es un poco complicado+ so"re todo+ por el mecanismo Aue usa para Cacer la llamada+ y Aue está contenido en el ficCero #srclass.#s+ Aue contiene la clase J*%;script>eAuest+ Aue será la Aue usemos para construir la llamada. Wa mecánica es la siguiente9 cada ve- Aue se introduce un nom"re de un pue"lo o ciudad de EspaBa+ se genera un evento+ y se llama a la función search. Esta función construye una petición+ dentro de la cual está incluido callbac,7get2ocation. El truco es Aue esa petición genera un call#ac" tal Aue cuando se reci"e la respuesta se llama a la función get2ocation Ddefinida más arri"aF. Esa función reci"e como varia"le en j9ata el resultado Aue+ al estar en formato J*%;+ ya está+ de CecCo+ en el formato de un o"#eto en J*. Por eso+ en el "ucle dentro de la función get2ocation se tra"a#a directamente con los datos o"tenidos sin necesidad de Cacer ning,n tipo de parsing.
!unciones como objetos Was funciones son o"#etos de pleno derecCo en Java*cript. *e puede crear una función como cualAuier otro o"#eto+ y de CecCo ya Cemos visto algo parecido cuando Cemos definido una clase DAue es simplemente un tipo de funciónF. !omo tales o"#etos+ podemos pasarlas como parámetros y modificarlas de diferentes formasH algo as
Cemos visto ya cuando Cemos definido o"#etos tam"i
efinición de la clase Partido function ;uevopartidoDlocal+visitanteF_ tCis.local Y localH tCis.visitanteYvisitanteH tCis.resultadoYnullH tCis.set>esultado Y set>esultadoH tCis.to*tring Y to*tringH tCis.settostring Y settostringH tCis.impresor Y to*tringH function set>esultadoD este>esultado F_ if D este>esultado YY S1S
este>esultadoYYS@S este>esultadoYYS2S F tCis.resultadoYeste>esultadoH function to*tringDF _ return tCis.impresorDtCis.local+ tCis.visitante+ tCis.resultadoFH function to*tringD local+ visitante F _ return \9 \ Z local Z \ \ Z visitante Z \ Y \ Z resultadoH function settostring D impresor F _ tCis.impresor Y impresorH En esta clase la principal diferencia es Aue usamos el m
fuera. e esta forma se puede modificar el comportamiento de un o"#eto9 asignamos un comportamieento por omisión+ pero si es necesario podemos cam"iar desde %uera el comportamiento de esa clase simplemente asignándole un valor nuevo. e CecCo+ esto es lo Aue vamos a Cacer en el programa siguiente Dliga.#sF9
QRusr"insm#s loadDS;uevopartido.#sSFH var eAuiposY ne= 0rrayDS$adridS+ SaraS+ S0tletiS+ S4etaS+ SetisS+ SeporS+ S*evillaS+ S4ranáSFH function #ornadaD estosEAuipos F _ var eAuipos0Aui Y ne= 0rrayH var imprime Y functionD local+ visitante+ resultado F _ printD\:mpimiendo bn\FH return \ \ Z local Z \ vs. \ Z visitante Z \ resultado \Z resultadoH H eAuipos0Aui Y eAuipos0Aui.concatDestosEAuiposFH var midsi-e Y eAuipos0Aui.lengtC2H
var Auiniela Y ne= 0rrayD midsi-e FH var uno@2 Y ne= 0rrayD S1S+S@S+S2SFH for D var iY/H i X midsi-e H iZZ F _ var eAuipo1 Y eAuipos0Aui.spliceD$atC.floorD eAuipos0 Aui.lengtC`$atC.randomDFF + 1FH var eAuipo2 Y eAuipos0Aui.spliceD$atC.floorD eAuipos0 Aui.lengtC`$atC.randomDFF+ 1FH Auiniela]i^ Y ne= ;uevopartidoD eAuipo1+ eAuipo2 FH Auiniela]i^.set>esultadoD uno@2]$atC.flo orD `$atC.randomDFF ^FH Auiniela]i^.settostringD imprime FH return AuinielaH var Auinielas Y ne= 0rrayH for D var i Y /H i X 1/H i ZZ F _ Auinielas]i^ Y #ornadaD eAuipos FH
var resultadosY ne= 0rrayH for D var i in eAuipos F _ resultados]eAuipos]i^^Y/H for D var i Y /H i X Auinielas.lengtCH i ZZ F _ for D var # Y /H # X Auinielas]i^.lengtCH # ZZ F _ var local Y Auinielas]i^ ]#^.localH var visitante Y Auinielas]i^ ]#^.visitanteH var resultado Y Auinielas]i^ ]#^.resultadoH s=itcC DresultadoF _ case S1S9 resultados]local^ZYH "rea5H case S@S9
resultados]local^ZY1H resultados]visitante^ZY1H "rea5H default9 resultados]visitante^ZYH for D var i in resultados F _ printD i Z \9 \ Z resultados]i^F Wa parte nueva de este programa está en en la lnea &+ donde se define la varia"le imprime. *e define una función sin nom#re Dlo Aue se suele denominar un closure o función anónimaF a la Aue podemos acceder mediante la varia"le Aue le Cemos asignado. Wo importante de esta sinta@is es Aue las funciones son vari"les de pleno derecCo+ Aue podemos usar como parámetros de otras funcionesH esto se usará de forma e@tensiva cuando veamos #uery y node.#s.
CommonJ"# una infraestructura com$n para carga de módulos 3no de los pro"lemas de J* es Aue+ al Ca"er sido desarrollado principalmente para tra"a#ar en el navegador+ carece de una serie de li"reras comunes para tra"a#ar en el servidor o en aplicaciones de escritorio. !ommonJ* es un intento de dar tal infraestructura. Principalmente se trata de proveer una serie de especificaciones para Cacer cosas comunes+ desde o más simple+ Aue es crear un módulo o li"rera Casta cosas más comple#as9 interacción con consola o con lnea de órdenes. Por lo pronto la especificación Aue Ca tenido más <@ito es la de módulos+ Aue se resume en este artculoH se trata de Aue un módulo escrito para un intCino+ por e#emploF pueda funcionar en otro Dtal como node.#sF. [amos a ver cómo adaptaramos alguna de las cosas CecCas a este estándar+ por e#emplo+ cam"iando esto so"re la clase ;uevopartido.#s creada anteriormente Dla llamamos 3nPartidoF.
[email protected]Partido Y function Dlocal+visitante+resultadoF _ tCis.local Y localH tCis.visitanteYvisitanteH tCis.resultadoYresultadoH
tCis.set>esultado Y set>esultadoH tCis.to*tring Y to*tringH tCis.settostring Y settostringH tCis.impresor Y to*tringH El ,nico cam"io Ca sido Aue en ve- de definir la función directamente+ se define como un atri"uto de exports. El resto+ al ser atri"utos de ese o"#eto+ no Cace falta Aue lo definamos de la misma forma. 0l llamarlo tam"i
var unpartido Y reAuireDS.3nPartido.#sSFH var estepartido Y ne= unpartido.3nPartidoD SesteS+SotroS+S1SFH console.logDS>esultado S Z estepartido.to*tringDFFH Este módulo ya se comporta como el resto de los módulos de ;ode+ Caciendo falta usar sólo reAuire Dcon el camino completoF para cargarlo. 0Cora+ con reAuire lo Aue definimos es un o"#eto+ y las funciones son atri"utos de ese o"#etoH por lo Aue a la Cora de declarar nuevos o"#etos de esa clase tendremos Aue Cacerlo con ne un_partido:n_"artido. 0 partir de aC el o"#eto
generado se comporta e@actamente igual Aue cualAuier otro o"#eto+ como podemos ver usando console. 0 diferencia de casi todos los lengua#es de scripting+ no Cay un modo estándar de instalar módulos Javascript+ aunAue algunos int
Para finali%ar !ualAuiera de los recursos Aue listo aC a"a#o pueden resultar ,tiles para ampliar información so"re Java*cript. ui-ás tam"i
&gradecimientos 0grade-co a los comentaristas de los diferentes anuncios Aue pu"liAu< en arrapunto sus comentarios y sugerencias. 7am"i
'ibliograf(a ay dos li"ros fundamentales para aprender J*+ aunAue están muy enfocados a J* en el navegador9 Javascript9 7Ce efinitive 4uide+ el li"ro del rinoceronte+ editado por %S>eilly+ Aue está disponi"le como recurso eletrónico en la 34> y Java*cript i"le+ de anny 4oodman+ un tocCo considera"le+ en el Aue Cay de todo+ y Aue viene con un ,til ! con e#emplos. 7am"iivas *antos.
Java"cript en el navegador y J)uery 7ra"a#ar con Javascript en el navegador
•
3sar li"reras populares de Java*cript en ese conte@to •
El modelo de objetos En realidad es difcil encontrar un enfoAue como el de este tema+ centrado en J* como lengua#e y no como un cCisme más dentro del navegador. Eventualmente+ Ca"rá Aue tratar con esto+ as Aue este momento es tan "ueno como cualAuier otro. En realidad+ la mayor diferencia entre J*sin navegador y J*connavegador es el "aga#e de o"#etos con el Aue tiene Aue tra"a#ar y tam"i
esta misma página+ Aue para eso está ya en 7$W. En (irefo@+ se ve el %$ completo con la com"inación de teclas !trlZ*CiftZ:. Para
página+ saldra algo as9
Wa estructura es la Aue ca"e esperar9 Cay un nodo ra-+ etiAuetado como document+ del Aue
descienden las dos partes del documento 7$W9 ;
XR%!7IPE 7$W P3W:! \G!7 7$W )./1 7ransitionalE;\M XCtmlM XCeadM XtitleMPrue"a document.=riteXtitleM Xscript typeYSapplication#avascriptSM function set!olorD color F _ document.getElementy:dDScolorSF.styl e."ac5ground YcolorH XscriptM XCeadM X"odyM XC1MPrue"a document.=riteXC1M XpMXinput typeYSte@tS nameYScolorS valueYS!olor Din inglisFS on!CangeYSset!olorDvalueFS MXpM Xdiv idYScolorSMn"spHn"spHXdivM XCrM XaddressMXa CrefY\mailto9#mereloTlocalCost.localdo main\MJuan J. $ereloXaMXaddressM XR !reated9 Ged (e" 21 189)9 !E7
2//' M XR CCmts start M Wast modified9 *un (e" 2 189'92 !E7 2//' XR CCmts end M X"odyM XCtmlM
Aue creara un %$ con el aspecto siguiente9
!omo se ve+ el nodo " sigue al nodo script+ es decir+ Aue el nodo se crea en el %$ #ustamente
siguiendo al nodo Aue incluye el script. En realidad+ se crean tantos nodos como a uno le interese+ pero de esta forma sólo se pueden colocar en el sitio donde está el script. 0s Aue Ca"rá Aue imaginar otra forma de Cacerlo. ;avegar por el modelo de o"#etos no es e@cesivamente complicado+ gracias a las funciones get+ Aue escogen elementos del %$ de acuerdo con alguna caracterstica. get
function putloAueDvalueF _ var e#s Y document.getElementy:dDSe#.71.SZvalu eFH
document.getElementy:dDSresultado1SF .inner7$WYe#s.te@t!ontentH 3n par de lneas sólo de J*9 una para "uscar el elemento Dla primeraF y la segunda para e@traer su contenido DtextContentF e introducirlo en otro+ el elemento resultado% Aue tenamos preparado al efecto. inner;?2 es el 7$W interno de un elemento9 al asignarle un valor+ efectivamente+ sustituimos parte del contenido de la página dinámicamente. ¿;o es una maravilla?
*sando +reaseMon,ey ;o se sa"e porAu< los temas de J* tienen tanta relación con los primates+ pero el CecCo es Aue 4rease$on5ey es un plugin para los navegadores $o-illa Aue permite instalar en el navegador programillas J* especficos de una página o grupo de páginas. Para tra"a#ar con
YY3ser*criptYY Tname 00P;av Tnamespace Cttp9geneura.orgpro#ectsgreasemon5 ey Tdescription ;avegación por las secciones de 00P Tinclude Cttp9geneura.ugr.esU#mereloasignat uras` YY3ser*criptYY 4$logDSEntrando 00P;avSFH var C2 Y document.getElementsy7ag;ameDSC2S FH var anodes Y ne= 0rrayH var ancCors Y ne= 0rrayH for D var secs Y /H secs X C2.lengtCH secs ZZ F _ var tCis0 Y C2]secs^.getElementsy7ag;ameDSaSFH anodes]secs^ Y tCis0]/^H
ancCors]secs^ Y tCis0]/^.get0ttri"uteDSnameSFH 4$logDS0ncCor S Z secs Z \ \ Z ancCors]secs^FH for D var secs Y /H secs X C2.lengtCH secs ZZ F _ var span Y document.createElementDSspanSFH span.set0ttri"uteDSstyleS+S"ac5ground9lig Ct"lueSFH if D secs M / F _ var aCref Y document.createElementDSaSFH aCref.set0ttri"uteDSCrefS+SQSZancCors]se cs1^FH var t@tY document.create7e@t;odeDSSFH
aCref.append!CildDt@tFH span.append!CildDaCrefFH if D secs X C2.lengtC 1 F _ span.append!CildDdocument.create7e@t ;odeDS SFFH var aCref Y document.createElementDSaSFH aCref.set0ttri"uteDSCrefS+SQSZancCors]se csZ1^FH var t@tY document.create7e@t;odeDSvSFH aCref.append!CildDt@tFH span.append!CildDaCrefFH anodes]secs^.parent;ode.inserteforeD span+anodes]secs^FH Este programa aBade unas flecCitas de navegación a los apuntes de esta asignatura+ de forma Aue se pueda pasar de cada sección a la anterior a la
siguiente Dde aC lo de aapnavF. 7iene dos partes9 la primera parte Calla las etiAuetas de navegación+ y la segunda las inserta. 7res partes+ de CecCo+ si incluimos las declaraciones del principio+ Aue son para uso y disfrute del propio 4rease$on5ey. Was dos primeras son terminológicas9 cómo se llama+ y Au< espacio de nom"res usa. Osto es para distinguir scripts con el mismo nom"re de diferentes fuentes. Wa tercera+ una descripción+ aparece en los directorios correspondientes y cuando gestionamos los scripts. El cuarto apartado es el más importante. Es un patrón de las páginas en las Aue va a funcionar el script. Oste no tendra sentido fuera de las páginas de las asignaturas Aue imparto+ as Aue incluimos en el mismo simplementa a las Aue Cay en ese directorio. !uando el navegador cargue alguna página con ese patrón+ 4$ lo detectará y cargará el script. El programa en s Cace uso de los elementos e@plicados en la sección anterior9 e@trae del documento los ttulos de captulo DC2F y de aC los anchor Da nameF y sus atri"utos+ metiendo todo lo meti"le en un "ucle. ace falta tenerlos todos en un array+ por eso se usa un segundo "ucle para insertar en la página los elementos de navegación. Este segundo "ucle crea elementos a tutipl
metiendo los elementos unos dentro de otros usando appendChild. I+ finalmente+ se insertan los elementos creados en el documento en la pen,ltima lnea9 anodes]secs^.parent;ode.inserteforeDspan+ano des]secs^FH Aue navega desde el ancla Casta su padre DparentodeF e inserta antes del mismo Dinsert6eforeF el span Aue Cemos creado previamente. El resultado+ si todo Ca ido "ien+ de"eras verlo en este mismo tutorial. 0demás+ Cace uso de algunas funciones propias de 4$9 D_log+ Aue escri"e en la consola de Javascript. $uy ,til para depurarlo+ in,til en producciónH pero si a"res la consola de J* verás los mensa#es Aue Ca usado.
-rabajando con otras ventanas 3na de las caractersticas especficas del %$ es la posi"ilidad de tra"a#ar con otras ventanas+ creando contenido y presentándolo en las mismas. Para eso se usa el o"#eto indoH lo interesante de este elemento eso Aue está incluido en el propio %$+ por lo Aue se puede usar desde Java*cript como Cacemos en el siguiente programa. ;o es Aue sea aconse#a"le+ por ciertoH de"e usarse sólo en caso de Aue sea imprescindi"le Da veces se usa para autenticación+ por e#emplo+ o para no crear
elementos nuevos en el interfa-F. Por e#emplo+ se Cace as en este programa
XR%!7IPE 7$W P3W:! \G!7 7$W )./1 7ransitionalE;\ \Cttp9===.=.org7>Ctml)loose.dtd\ M XCtmlM XCeadM Xmeta Cttp eAuivY\!ontent7ype\ contentY\te@tCtmlH cCarsetYiso88&1\M XtitleMPro"ando =indo=.openXtitleM Xscript typeYSapplication#avascriptSM var contenido Y \XCtmlMXCeadMXtitleM$i ventanitaXtitleMXCeadMX"odyMXC1 M$i ventanitaXC1MX"odyMXCtml\H ne==indo=Y=indo=.openDFH ne=documentYne==indo=.documentH ne=document.=riteDcontenidoFH XscriptM En este caso+ se crea una nueva página estática usando rite so"re el documento Aue Cemos creado. ;o es Aue sea demasiado ,til Dse podra usar el 3>W directamente pasándoselo como parámetro a openF pero demuestra las posi"ilidades del mismo+ Aue tam"i
"electores Was Co#as de estilo !** son una especificación de la apariencia de elementos tanto 7$W como K$W Aue permiten asignar parámetros de presentación especfico a cada elemento o a grupos de ellos. ;o es el o"#etivo de esta asignatura enseBarlas+ pero su utilidad va más allá de la mera apariencia+ permitiendo designar Dusando :sF y agrupar Dusando clasesF elementos o grupos de los mismos. !uando Cemos Ca"lado anteriormente de seleccionar un solo elemento por la id+ estamos usando un tipo de selector "ásicoH sin em"argo+ si Aueremos tra"a#ar con selectores más generales Dcomo Caremos más adelanteF es conveniente Aue se aprenda la sinta@is de !** Aue es la Aue se usa de forma más general. Wa sinta@is más general está especificada por la G y se puede o"servar en cualAuier Co#a de estilo+ por e#emplo la de esta misma página. e esta+ e@traemos los / selectores Aue se de"en memori-ar+ principalmente # Aue se refiere a un id especfico Dpor e#emplo+ #ej%% seleccionara un div declarado como div id7@ej%%%@ y Aue se refiere a una claseH ej por e#emplo seleccionara todos los div declarados as9 div class7@ej@.
Eventos Para entender "ien el uso de Java*cript en el navegador es conveniente introducir el concepto
de eventos. *e trata simplemente de seBales generadas por el mismo+ o "ien registradas por el usuario Des decir+ introducidas por el usuario cuando suceda algo determinadoF. El navegador+ por e#emplo+ genera un evento cuando el ratón entra o sale de un elemento+ cuando se carga la página+ o cuando se pulsa el ratón so"re un elemento activo. e la lista de todos los eventos y de los elementos a los Aue afectan. afectan . Wos eventos permiten por un lado tra"a#ar con un patrón de programación reactiva+ en la Aue se reacciona a lo Aue va sucediendo en el navegador y+ a la ve-+ un cierto grado de concurrencia porAue cada evento sucede en una Ce"ra diferente. 7am"i
completo o Aue no lo est
XR%!7IPE 7$W P3W:! \G!7 7$W )./1 7ransitionalE;\ \Cttp9===.=.org7>Ctml)loose.dtd\ M XCtmlM XCeadM Xmeta CttpeAuivY\!ontent7ype\ contentY\te@tCtmlH cCarsetYiso88&1\M XtitleMPro"ando onWoadXtitleM XCeadM X"ody onWoadYSalertD\0Cora está todo cargado\FSM XC1MEsta es una página Aue no tiene gran cosaXC1M XpMPero podra tenerla.XpM El uso de evento está Cacia el final del código+ donde usamos alert Aue se activa tras el evento load+ es decir+ cuando se carga la página
J)uery. Introducción Juery es una li"rera en Java*cript Aue está Juery es diseBada principalmente para simplificar la creación de programas y permitir crear interfaces ricos de usuario. Juery usuario. Juery se se Ca populari-ado desde
su creación en el aBo 2//6 Casta el punto Aue se calcula Aue se usa en más de la mitad de los sitios más populares. Por supuesto+ es soft=are li"re con una licencia $:7. $:7. a sido aceptada tam"i
XCtmlM XCeadM Xmeta CttpeAuivY\!ontent7ype\ contentY\te@tCtmlH cCarsetYiso88&1\M Xscript srcY\Cttp9a#[email protected]a#a@li" s#Auery1.&.1#Auery.min.#s\MXscriptM XtitleMPro"ando ready de #ueryXtitleM XCeadM X"odyM XC1MEsta es una página Aue no tiene gran cosaXC1M XpMPero podra tenerla.XpM Xscript typeYSte@t#avascriptSM V
DdocumentF.readyDfunctionDF _ alertDS0Cora estamos listosSFH FH XscriptM En este caso+ usamos como se Ca indicado antes la copia de Juery proporcionada por 4oogle+ Aue+ como cualAuier otra li"rera J*+ de"e ser incluida en nuestra página para ser usada. Por otro lado+ la ,nica función Aue usamos de JAuery está tras el párrafo9 cuando el documento está listo DreadyF+ lan-amos un alert. Este script funciona e@actamente igual Aue como el Aue Ca"amos visto anteriormente. e CecCo+ se puede simplificar e incluso aCorrar la orden para pasar directamente a la función Aue Aueremos Aue se active cuando se cargue la página. Juery tam"i
Xscript typeYSte@t#avascriptSM VDfunctionDF _ var CacCedoses YSSH VD\C2\F.eacCD functionDF _
CacCedoses ZY tCis.te@t!ontent Z \ \H FH alertDCacCedosesFH VD\Qcam"iando\F .CtmlD CacCedoses FH FH XscriptM XC2MEste es un 2XC2M XC2MEste es otro 2XC2M X2MI este+ lo adivinaste+ otroX2M Xdiv idYScam"iandoS styleYS"order9dasCedSM XdivM En este e#emplo+ primero se recorren los elementos h pero en ve- de Cacerse a partir de un "ucle se usa directamente el o"#eto generado por el selector y Aue aplica a cada uno de ellos una función anónimaH en este caso la función concatena a hachedoses el contenido en te@to del elemento. 3samos el alert principalmente para Aue se vea el contenido del div definido más a"a#o vaco y posteriormente con el contenido Aue se le aBade en la ,ltima lnea del script+ Aue usa como selector el eAuivalente a un elemento con el id #cambiando.
Introducción a node/js !onocer node.#s y sa"er sus conceptos fundamentales. 0prender los conceptos "ásicos de los servicios =e" "asados en >E*7+ la representación de datos usada y cómo implementarlos en node.#s >eali-ar prototipos rápidos de cliente y servidor de servicio =e" usando node.#s •
•
•
0ode/js# un int1rprete as(ncrono para J" Wa aceptación de J* como un lengua#e de programación procede del CecCo de su incorporación en diferentes Cerramientas de propó@ito general+ y so"re todo de Ca"erlo desga#ado del navegador. 3na de tales Cerramientas es ;ode.#s+ un sistema para programación de eventos asncrono Aue usa como "ase J*. *e puede usar directamente como int
es Aue sea algo e@traBo dentro del mundo J*+ puesto Aue es la misma forma de tra"a#ar Aue tiene Juery. En todo caso+ node.#s convierte J* en un lengua#e de propósito general+ algo Aue le falta a otros intCino+ Aue necesita usar li"reras de Java para poder Cacer cosas "ásicas como a"rir ficCeros. Empecemos pues+ por el principio9 instalar node.#s+ lo Aue se puede Cacer en Winu@ fácilmente con sudo aptFget install nodejs+ desde los repositorios+ o descargándoselo desde su =e". !onviene usar este ,ltimo m
QRusr"innode var saludo Y ne= %"#ectH saludo.Cola Y SmundoSH console.logD saludo FH Wa primera lnea es e@clusivamente para sistemas Winu@ DAue son+ por otro lado+ los ,nicos serios para desarrollo de soft=areFH en ella Ca"rá Aue poner el camino completo al int
+x nodejs podemos e#ecutarlo y o"tener el
siguiente resultado
#mereloTpenny9Uservicios =e"e#emplosV .guenas.#s _ Cola9 SmundoS En otro entorno Do si no se Auiere Cacer al ficCero e#ecuta"leF+ con escri"ir
#mereloTpenny9Uservicios =e"e#emplosV node guenas.#s es suficiente. En cualAuier caso+ la salida será la misma. I la e@plicación tam"i
QRusrlocal"innode fs Y reAuireDSfsSFH fs.read(ileDSAuiniela.datosS+ Sutf8S+ functionDerr+datosF _
if DerrF _ return console.logDerrFH H var filas Y datos.splitD\bn\FH for D var f in filas F _ var cacCos Y filas]f^.splitD\ \FH var partido Y _ SlocalS9 cacCos]/^+ SvisitanteS9 cacCos]1^+ SresultadoS9 cacCos]2^ H console.logD partido FH FH En este programa DAue act,a so"re este ficCero de datosF se usa el int
asncrona. En general+ el patrón de las funciones en node+ en ve- de ser Ca-aDFH Ca-"DFH Aue e#ecutara haz_a+ y+ tras terminar+ e#ecutara haz_b+ es Ca-aDparametros+ Ca-"FH Ca-cDF Aue viene a decir e#ecuta haz_a so"re unos parametros y+ cuando veas Aue Cas terminado+ llama a la función haz_bH fi#aros Aue se trata de un puntero a función+ no una llamada a la misma Dno lleva par
nodejs leer las cosas con mucCa eficiencia+ y
Cacer una serie de operaciones Aue no se pueden Cacer fácilmente con otros lengua#es. !oncentr
_ local9 S$adridS+ visitante9 SaraS+ resultado9 S@S _ local9 S0tletiS+ visitante9 SaraS+ resultado9 S1S _ local9 S0tCletiS+ visitante9 S>ecreS+ resultado9 S1S _ local9 SeporS+ visitante9 S0tCletiS+ resultado9 S2S
_ local9 SElcCeS+ visitante9 SecreS+ resultado9 S1S Es decir+ los datos ledos en formato J*%;.
npm# instalación de módulos en
0ode fs es sólo el principio de una serie de módulos
muy interesanteH de CecCo+ es un módulo Aue se instala por omisión. ay un módulo para crear servidores =e"+ pero lo veremos más adelante Dsólo para tener una idea se puede visitar nodetutsF. En el sitio de descarga de node#s vienen tam"i
mayora de los servicios =e" y aplicaciones actuales. :nstalemos por e#emplo reAuest+ una de las li"reras más populares+ Aue act,a como cliente de 77P. 3na ve- instalado npm+ se escri"e Den el directorio donde lo vayamos a usar+ en generalH la poltica de módulos de ;ode es tener los módulos instalados #unto con la aplicación Aue los usa+ en ve- de en un sitio centrali-adoF npm install re(uest. Esta orden+ si la cone@ión a :nternet está disponi"le+ descargará e instalará el módulo en el directorio desde la Aue la llamemos. *i se e#ecuta por primera ve-+ creará un directorio node_modules+ dentro del cual Ca"rá un directorio re(uest. !on re(uest podemos codificar todo tipo de peticiones >E*7. 0 un nivel muy "ásico se puede usar de la forma siguiente+ en el programa gitCu" get.#s+ Aue pide información so"re un usuario en 4itu"9
QRusr"innode var Cttps Y reAuireDSCttpsSFH var user Yprocess.argv]2^? process.argv]2^9SJJSH var options Y _ Cost9 Sapi.gitCu".comS+ patC9 SusersSZuser+ metCod9 S4E7S H var reA Y
Cttps.getDSCttps9api.gitCu".comusersS Zuser+ functionDresF_ res.setEncodingDSutf8SFH res.onDSdataS+ function DdatosJ*%;F _ var datosY J*%;.parseDdatosJ*%;FH console.logDSWogin9 S Z datos.login Z \bn;om"re9 \ Z datos.name Z \bn\FH FH FH reA.endDFH 3samos la li"rera reci
anterior de apertura de un ficCero. 0 la función se la llama con tres parámetros9 o "ien err+ en caso de Aue se produ-ca un error+ o "ien response y body en caso de Aue la respuesta sea correcta. body contendrá el te@to de la respuesta+ Aue Ca"rá Aue decodificar Do imprimir tal cual+ en caso de Aue se trate de 7$WFH response es una estructura de datos comple#a+ Aue podemos imprimir con consolelog Dy saldrá un montón de cosas+ incluyendo la versión de 77P+ las ca"eceras+ y mucCa información másF+ pero Aue contiene+ entre otras cosas+ el estado de la petición+ con un código del protocolo 77P. En el programa anterior se compro"a"a sólo si Ca"a error o noH aCora demás compro"amos Aue el código devuelto es el correcto+ es decir+ 2//. *i Cu"iera un código )//+ o //+ o incluso un 2/1+ tendramos Aue interpretar la respuesta de otra forma.
*sando un servidor 2eb Para escri"ir posi"les respuestas a una petición =e" Cay Aue Cacerlo desde un servidor. Wa tendencia moderna es Cacerlo desde un entorno integrado+ sin em"argo los servidores =e" multifunción permiten tanto ofrecer páginas =e" estáticas como =e"s dinámicas+ y además Cacerlo desde una variedad de lengua#es de programaciónH por eso conviene conocer+ al menos+ cómo instalar un servidor =e" simple y Cacer programas Aue funcionen desde
El clásico 0pacCe sigue usándose e@tensivamente+ aunAue ,ltimamente se están empe-ando a usar otras opciones como el ngin@+ un servidor =e" de altas prestaciones Aue se puede isntalar+ además+ en todo tipo de plataformas DaunAue este ,ltimo no puede e#ecutar+ de forma directa+ los !4:s de los Aue Ca"lamos en este apartadoF. 7anto uno como otro están disponi"les en los repositorios de las distri"uciones Winu@ más comunes. 3n servidor =e" se instala como un servicio Des decir+ un programa Aue se Aueda e#ecutándose en memoria permanentementeF y escucha un puerto 7!P:P+ normalmente el 8/H este puerto+ en Winu@+ está reservado Dcomo todos Casta el &&&F al superusuario+ as Aue Cay Aue e#ecutarlo con esos privilegios. 3na ve- instalado se pueden servir tanto páginas estáticas DCa"rá Aue consultar en la documentación para ver cuál es el directorio configurado para CacerloF como dinámicas Duna ve- más+ tam"iW Aue se le solicita. Para servir contenidos desde un programa+ la forma Ca"itual es copiar el programa con la e@tensión .cgi al directorio Aue se Caya
configurado para ello. e la forma más simple posi"le un !4: escrito en node.#s podra ser el siguiente9
QRusr"innode ca"ecera console.logDS!ontent7ype9 te@tplainH cCarsetY37(8SFH contenido var unavaria"leY]SunoS+SdosS+_ tres9 StresS^H console.logDSSFH console.logDunavaria"leFH Para e#ecutarlo no Cay más Aue copiarlo a un directorio determinado con permisos de e#ecución para otros Dchmod +x holaFjscgiF.Wa primera enva una ca"ecera al cliente Aue le indica el tipo Aue se usaH la segunda parte es la Aue efectivamente enva el contenido+ en este caso una varia"le en J*%; Drecordad Aue console.log escri"e en salida estándar+ y convierte las estructuras de datos a J*%;F. ;ode+ por su naturale-a asncrona+ realmente no es el me#or sistema para tra"a#ar con Java*cript en un servidor Aue incluya otros lengua#es. *in em"argo+ se puede usar Javascript de mucCas maneras diferentes9 *il5J*+ por e#emplo+ es un int
=e"H o 7eaJ* es un sistema para crear !4:s "asado en el intu"y o Perl.
node/js como servidor !rear un servidor =e" con node.#s es tan simple Aue viene directamente en la página principal del mismo
var CttpYreAuireDSCttpSFH Cttp.create*erverDfunction DreA+ resF _ res.=riteeadD2//+ _S!ontent 7ypeS9 Ste@tplainSFH res.endDS0C estamosbnSFH F.listenD8/8/+ S12'././.1SFH console.logDS*erver running at Cttp912'././.198/8/SFH Este programa simplemente escri"irá \0C estamos\ en el navegador cuando se solicite el 3>W. ;ada complicado+ pero tampoco lo es el programa9 se usa un módulo Cttp Aue es estándar en ;ode en la primera lnea del programaH se crea un servidor con createerver. Esta orden reci"e como parámetro la función a la Aue Cay Aue llamar
cada ve- Aue se reci"a una petición. !uando se reci"e una petición+ se llama a una función Aue escri"e primero la ca"ecera 77P Drite;eadF y termina DendF el servicio de la misma escri"iendo el contenido Aue nos aparecerá en el navegador. httpcreateerver crea un o"#eto y lo devuelveH
en este caso+ no lo asignamos a ninguna varia"le+ sino Aue so"re el mismo o"#eto DanónimoF le decimos con listen en Au< puerto D8/8/F y dirección Dla del propio ordenador+ there's no place li"e ()*.+.+.(F va a escucCar el servidor. Es una orden Aue se e#ecuta de forma asncrona+ con lo Aue lo Aue crea es un call#ac" Aue se llamará cada ve- Aue se llame a ese 3>W. *ólo los puertos por encima de 1/2) están accesi"les al usuario+ as Aue tendr
var CttpYreAuireDSCttpSFH Cttp.create*erverDfunction DreA+ resF _ res.=riteeadD2//+ _S!ontent 7ypeS9 Ste@tplainSFH res.endDS0C estamos S Z reA.urlFH
F.listenD8/81+ S12'././.1SFH console.logDS*ervidor e#ecutándose en Cttp912'././.198/81SFH Wa principal diferencia entre este programa y el anterior es+ aparte del puerto usado D8/81 en vede 8/8/F la lnea en la Aue escri"e algo+ y en la Aue usa la varia"le re(+ un o"#eto Aue contiene información so"re la petición+ y entre otras cosas el 3>W Duna ve- eliminada la parte del servidorF Aue se Ca usadoH este 3>W es el Aue se escri"e a continuación de \0C estamos\+ tal cual. En general+ para programar un servicio =e" Ca"rá Aue tra"a#ar con esa petición DAue será la Aue reci"a la orden del 0P:F y actuar seg,n la misma+ y teniendo en cuenta tam"iE*7 para responder a una serie de peticiones. Wa idea "ásica es Aue las funciones a las Aue tendremos Aue llamar estarán indentificadas por el 3>W Aue se use para pedirlas. Por e#emplo+ el programa restminimo.#s
var CttpYreAuireDSCttpSFH var puertoYprocess.argv]2^? process.argv]2^98/8/H Cttp.create*erverDfunction DreA+ resF _
res.=riteeadD2//+ _S!ontent 7ypeS9 Ste@tplainSFH var spliturlYreA.url.splitD\\FH if D spliturl]1^ YY SS F _ res.endDSPortadaSFH else if D spliturl]1^ YY SprocS F _ res.endDS;o es la portadaSFH else _ res.endDS;o entiendo la peticiónSFH F.listenDpuerto+ S12'././.1SFH console.logDS*erver running at Cttp912'././.19SZpuertoZSSFH En este programa procesamos+ no sólo imprimimos+ la varia"le re(. Es una estructura de datos con un montón de cosas Dinsertad un console.log si AuerW lo Aue descri"e es un recurso+ no un ficCero+ as Aue nosotros procesamos el 3>W parti
diferente+ y eventualmente si se trata de un 3>W desconocido devolvemos un mensa#e diferente. 0dicionalmente+ Cemos introducido en este programa un puerto Aue se toma de la lnea de órdenes. processargv contiene información so"re la lnea de órdenes y otras cosasH en el 2h elemento es donde está+ precisamente+ el primer argumento de la lnea de órdenes. El puerto por omisión será 8/8/ Dlo Aue se ve en la segunda lneaF+ pero si se pasa alg,n argumento Dy es un puerto válidoF se usará ese valor. 0lgunos sitios =e" como ero5u o ;odester permiten pu"licar de forma gratuita aplicaciones =e" CecCas con node.#s. Pueden ser "astante ,tiles para crear prototipos o para Cacer prue"as+ incluso para alo#ar prácticas de alguna asignatura.
Para finali%ar ay mucCas más cosas Aue se pueden Cacer con ;ode. Por e#emplo+ un gestor de ventanas. !on app#s puedes construir aplicaciones cliente servidor con su propia ventana+ igual Aue con el más veterano node=e"5it. *i se Auiere tra"a#ar principalmente en el navegador+ #uery funciona de forma muy similar a node9 es un entorno asncrono para crear aplicaciones desde el navegador fácilmente+ sin tener Aue escri"ir demasiado código Java*cript. 7rasladar un programa de node a Juery+ es "astante directo+ y e@isten diversidad de
ampliaciones DpluginsF para #uery Aue Cacen la vida DtodavaF más fácil. Por otro lado+ cualAuier lengua#e de scripting como PytCon o Perl permite crear tam"iecuerda Aue tu 5arma aumentará tam"i
&gradecimientos 0grade-co a los lectores en 7=itter+ especialmente Tdanielri"es+ sugerencias so"re este material.
'ibliograf(a !omo recursos adicionales+ las páginas de Javascript en $o-illa.org+ el estándar completo+ EloAuent Javascript y el curso de Javascript de [ctor >ivas *antos. Por ,ltimo+ Javascript9 7Ce good parts es un manual "astante completo Aue menciona mucCos trucos para tra"a#ar con este lengua#e. Especficamente de node.#s+ se puede empe-ar por esta pregunta en *tac5%verflo=+ para seguir con el sitio de node.#s en espaBol+ Aue incluye enlaces
a node"eginner+ el li"ro para principiantes en node.#s. Wa traducción tiene algunos errores+ pero es legi"le. (inalmente+ %psou nos ofrece una lista de tutoriales en espaBol. (inalmente+ tam"i
-rabajando con 3E"- y &J&4 0prender los conceptos generales de los interfaces >E*7. Programar clientes y servidores para >E*7 usando diferentes lengua#es de programación :ntroducción a 0#a@ y otras t
•
•
Introducción al interfa% 3E">E*7 es una serie de convenciones en la interacción clienteservidor so"re el protocolo 77P. En la práctica+ un interfa- >E*7 es un interfa- de programación de aplicaciones Aue usa+ para acceder al servidor+ el con#unto completo de órdenes del protolo 77P y confa en los mensa#es informativos y de error del mismo. 0unAue se trate de un hermano menor de otros tipos de servicios =e" DAue se verán más adelante
en este cursoF+ su popularidad se de"e so"re todo al poco overCead Aue aBade a las peticiones y a la facilidad de su uso+ tanto en el cliente como el servidor. 7am"iE*7 es tan fácil como crear una cadenaH de CecCo+ se pueden usar desde la lnea de órdenes
El protocolo 5--P y sus m$ltiples posibilidades El protocolo 77P es uno de los protocolos más infrautili-ados de la Cistoria. 0 pesar de Aue ofrece m,ltiples posi"ilidades y versiones+ se usa simplemente para enviar y reci"ir información de un servidor. Para reci"ir información se usa la orden D+ y para enviar+ la orden ".?. Pero tam"i:+ y es la mnima acción Aue un servidor puede reali-ar. !omo caractersticas adicionales+ la acción de algunas peticiones D D y ;
idempotentes9 el Cacer varias veces la misma
petición tiene el mismo efecto Aue el Cacerla una sola ve-. 77P funciona puramente como clienteservidor9 se Cace una petición+ y se espera la respuesta. Wo Aue no Auiere decir Aue no se puedan Cacer peticiones concurrentes y asncronasH sin em"argo+ esas peticiones tendrán Aue estar dentro del marco de una página =e" Do sea+ una aplicaciónF. 0 las peticiones el servidor responde con una serie de códigos estándar+ Aue usan la misma presentación Aue la petición9 te@to puro y duro. !uando todo va "ien+ la respuesta es GG .HH los códigos xx corresponden+ en general+ a una petición CecCa+ y fuera de los 2@@ e@iste el caos y el descontrol. En especial+ un código // implica error en el servidor. Evidentemente+ estos mensa#es están pensados para Aue los lea un cliente en el navegadorH sin em"argo+ cuando tra"a#amos directamente so"re este protocolo+ nuestro programa de"erá ser consciente de ellos y responder de forma adecuada como si se tratara de una llamada a otro procedimiento. Was aplicaciones construidas alrededor del protocolo 77P y sus caractersticas se suelen llamar aplicaciones >E*7ful D>E*7 YY >Epresentational *tate 7ransferF. Wa idea de >E*7 es Aue se transfiere el estado del servidor al cliente. 3n recurso tiene una representación+ Aue se transfiere al cliente por una peticiónH esa
representación se puede cam"iar con diferentes operaciones. *in em"argo+ con esto sólo estamos especificando la capa más "a#a del servicio =e"H Cace falta una capa de mensa#era. I esta capa de mensa#era se suele denominar P%K P%K++ o Plain ld -M DK$W de toda la vidaF+ es decir K$W "ien formado con algunas ampliaciones+ pero sin ning,n tipo de validación. En algunos casos se usa te@to directamente+ aunAue tam"iE*7 suelen ser más populares Aue populares Aue otros servicios =e"+ por el simple CecCo de Aue es muy fácil construir el interface9 simplemente creando una cadena determinada. Eso los Cace tam"iE*7ful+ y está "astante "ien diseBada. Para usarla es necesario darse de altaH desde la versión 1.1 del interfatodas las peticiones necesitan autenticación. 0s Aue usaremos otro interfa-+ el de 4itu"+ 4itu"+ para Cacer prue"as. Por e#emplo+ esta petición te dará todas las organizaciones a las Aue pertenece el usuario JJ usuario JJ99
"asCV curl i Cttps9api.gitCu".comusersJJorgs
Para llevar a ca"o este e#emplo Cay Aue instalar curl+ un programa Aue en una primera apro@imación es simplemente un descargador de páginas =e" pero Aue en segunda se puede usar como un completo cliente >E*7H en este caso Fi te incluye las ca"eceras en la salida+ con lo Aue producirá algo de este estilo
77P1.1 2// %N *erver9 4itu".com ate9 (ri+ 2 %ct 2/1 1698926 4$7 !ontent7ype9 application#sonH cCarsetYutf8 *tatus9 2// %N K >ateWimitWimit9 6/ K>ateWimit >emaining9 ' K>ateWimit>eset9 182'2&6 !acCe!ontrol9 pu"lic+ ma@ageY6/+ sma@ageY6/ E7ag9 \86e6'6///)'/d12/c6f2d66&ec \ [ary9 0ccept K4itu"$edia7ype9 gitCu"."eta K!ontent7ype%ptions9 nosniff !ontentWengtC9 1// 0ccess !ontrol0llo=!redentials9 true 0ccess !ontrolE@poseeaders9 E7ag+ Win5+ K >ateWimitWimit+ K>ateWimit>emaining+ K>ateWimit>eset+ K%0utC*copes+ K 0ccepted%0utC*copes 0ccess!ontrol 0llo=%rigin9 ` K4itu">eAuest:d9 !E91(09208101926002 [ary9 0cceptEncoding ] _ \login\9
\open5ratio\+ \id\9 21/26+ \url\9 \Cttps9api.gitCu".comorgsopen5ratio\ + \reposurl\9 \Cttps9api.gitCu".comorgsopen5ratio repos\+ \eventsurl\9 \Cttps9api.gitCu".comorgsopen5ratio events\+ \mem"ersurl\9 \Cttps9api.gitCu".comorgsopen5ratio mem"ers_mem"er\+ \pu"licmem"ersurl\9 \Cttps9api.gitCu".comorgsopen5ratio pu"licmem"ers_mem"er\+ \avatarurl\9 \Cttps91.gravatar.comavatarda62&/ f)a8'ec/)cd""8d/'2ad?dYCttps L0L2(L2(identicons.gitCu".com L2(&a/686"2cd6a/d12a&cdf6ee&// 1ca.pngrY@\ + _ \login\9 \!0;3E\+ \id\9 8&8/8+ \url\9 \Cttps9api.gitCu".comorgs!0;3E\+ \reposurl\9 \Cttps9api.gitCu".comorgs!0;3Ere pos\+ \eventsurl\9 \Cttps9api.gitCu".comorgs!0;3Eev ents\+ \mem"ersurl\9
\Cttps9api.gitCu".comorgs!0;3Em em"ers_mem"er\+ \pu"licmem"ersurl\9 \Cttps9api.gitCu".comorgs!0;3Epu "licmem"ers_mem"er\+ \avatarurl\9 \Cttps9identicons.gitCu".com6f"6"f6 fdd6'8&"&ff)8ffa&'d/8.png\ ^ !asi todos los servicios =e" incluyen alguna forma de autentificaciónH una de las formas de Cacerlo es incluirlo en el propio 3>W+ en la forma Ca"itual9 usuarioIclaveJhostH en este caso no es necesario y en la mayora de los 0P: >E*7 se usa ya autentificación %0utC en alguna de sus formas. I lo ,nico Aue Cacemos con la respuesta es imprimirla+ tal cual+ pero lo me#or sera e@traer información ,til de la misma+ como ocurre en este programa en node.#s9
QRusr"innode var Cttps Y reAuireDSCttpsSFH var user Yprocess.argv]2^? process.argv]2^9SJJSH var options Y _ Cost9 Sapi.gitCu".comS+ patC9 SusersSZuser+ metCod9 S4E7S H
var reA Y Cttps.reAuestDoptions+ functionDresF _ res.setEncodingDSutf8SFH res.onDSdataS+ function DdatosJ*%;F _ var datosYJ*%;.parseDdatosJ*%;FH console.logDSWogin9 S Z datos.loginZ \b n;om"re9 \ Z datos.name Z \bn\FH FH FH reA.endDFH Este programa descarga información de un usuario en J*%; y la procesa. 7oma el usuario Aue se pase por la lnea de órdenes+ o "ien usa 33 por defecto+ dando un resultado as
"asCV node codegitCu"get.#s Wogin9 JJ ;om"re9 Juan Julián $erelo 4uervós El programa Cace una petición 4E7 al 0P: de 4itu" y del o"#eto en J*%; devuelto e@trae Dtras su conversión en un o"#eto J* con 3.parse un par de varia"les del mismo y las imprime. El o"#eto contiene mucCas más cosas Aue no nos interesan. El módulo Cttps usado es muy similar al http+ salvo por el protocolo usado. Wa petición Aue se está usando es la forma más general+ pero se puede usar directamente get de esta forma9 var
re( 7 httpsget&@httpsI//apigithubcom/users/@+ user1 function&res' con e@actamente el mismo
resultado. Wa idea de >E*7 desde el punto de vista del servidor es usar el 3>W para representar recursos+ y las propias órdenes de 77P para e#ercitar acciones so"re ese recursos. En general+ D servirá para transferir la representación de un recurso del cliente al servidor+ ".? cam"iará el estado de un recurso+ ":? DAue no se suele usar tan a menudoF directamente cam"iara la representación del recurso+ mientras Aue 9<2< "orrara el recursoH a estas arAuitecturas se les suele denominar tam"i
Por eso tam"iE*79 Wa funcionalidad está divida en recursos *e usa una sinta@is universal "asada en 3>W 7odos los recursos tienen un interfauniforme+ con un con#unto "ien definido de operaciones y un con#unto restringido de tipos de contenido. En particular+ este interfaesconde los detalles de la implementación. • • •
Por e#emplo+ supongamos Aue Cay Aue diseBar un interfa- >E*7 para una Auiniela deportiva. ay una Auiniela por #ornada+ y cada #ornada tiene 1 partidos. *upongamos Aue se conocen los partidos de antemano+ y Aue sólo se pueden proponer
resultados por parte de un usuario. *e podra diseBar el interfa- de la forma siguiente. uiniela de una #ornada9
•
httpI//jostcom/(uiniela/jornada/ )nKmero de jornada*
3n partido de una Auiniela9
•
httpI//jostcom/(uiniela/jornada/ )nKmero de jornada*/partido/)nKmero de partido*
Para los resultados+ Ca"ra Aue sustituir (uiniela por resultados. 0dicionalmente+ aBadir usuario/)nombre de usuario*+ para recuperar los resultados propuestos por un usuario determinado. Por e#emplo+ >esultados9 •
httpI//jostcom/resultados/jornada//u suario/foobar
Was operaciones vienen dadas por el diseBo del interfa-. Por e#emplo+ para proponer un resultado determinado Ca"ra Aue Cacer una petición P%*7 con dos parámetros9 el nom"re de usuario y el resultado propuesto. El servidor responderá con un mensa#e estándar 77P y un ficCero K$W si se Ca podido Cacer correctamente+ y con un error 77P si no. El principal pro"lema con este diseBo >E*7ful es Cacerlo en la práctica. !omo se Ca visto a la Cora de programar !4:s+ en general el camino a un recurso es tortuoso+ y la forma como se pasan los parámetros tiene un montón de e signos Y. 0s Aue Cay Aue limpiar el 3>W de alguna forma. ependiendo de la implementación del servidor+
Aui-ás se puede Cacer directamenteH por e#emplo+ en caso de Aue se trate de un ar en un contenedor de servlets+ ya se encarga directamenteH sin em"argo. 0lgunos !4:s tam"iW. Pero otra forma de Cacerlo es usar modre=rite+ Aue permite reescri"ir los 3>Ws+ de forma Aue la petición cam"ia de forma antes de servirse la petición. Estos cam#ios toman la forma de directivas del servidorH por e#emplo+ en 0pacCe podramos usar la siguiente Ddentro del ficCero httpdconf o el ficCero de configuración de un directorio en particular+ htaccess9 >e=rite>ule AuinielaDb=ZFDbdZFDb=ZFDbdZFV U#merelo>E*7Auiniela.cgi?V1YV2VYV) ]W^ Parece un poco complicada+ pero no lo es. Para empe-ar+ se cam"iará la e@presión regular de la i-Auierda por la de la derecCa. Wa de la i-Auierda incluye pala"ras Db=ZF y n,meros DbdZF+ y en la e@presión de la derecCa aparecen+ por orden+ representados por En. El CecCo de Aue sea tan complicado diseBar interfaces >E*7 con recursos+ como los !4:s+ Aue no están preparados para ello Cace Aue e@istan marcos de aplicaciones+ como los Aue veremos a continuación+ en los Aue todo esto se Cace de una forma mucCo más simple+ tra"a#ando directamente con las rutas >E*7
Interfaces 3E"- simples con e6press Para diseBar interfaces >E*7 de forma "astante simple+ Cay un módulo de node.#s llamado e@press. Wa idea de este módulo es refle#ar en el código+ de la forma más natural posi"le+ el diseBo del interfa- >E*7. Pero primero Cay Aue instalarlo. ;ode.#s tiene un sistema de gestión de módulos "astante simple llamado npm Aue Cemos visto en el tema anterior. 7ras seguir las instrucciones en el sitio para instalarlo Do+ en el caso de u"untu+ instalarlo desde *ynaptic o con aptgetF+ vamos al directorio en el Aue vayamos a crear el programa y escri"imos npm install express
en general+ no Cace falta tener permiso de administrador+ sólo el necesario para crear+ leer y e#ecutar ficCeros en el directorio en el Aue se est< tra"a#ando 7ras la instalación+ el programa Aue Cemos visto más arri"a se transforma en el siguiente9
var e@pressYreAuireDSe@pressSFH var app Y [email protected]*erverDFH app.getDSS+ function DreA+ resF _ res.sendDSPortadaSFH FH app.getDSprocS+ function DreA+ resF _ res.sendDS;o es la portadaSFH FH app.listenD8/8/FH
console.logDS*erver running at Cttp912'././.198/8/SFH Para empe-ar+ express nos evita todas las molestias de tener Aue procesar nosotros la lnea de órdenes9 directamente escri"imos una función para cada respuesta Aue Aueramos tener+ lo Aue facilita mucCo la programación. Was órdenes refle#an directamente las órdenes de 77P a las Aue Aueremos responder+ en este caso get y por otro lado se pone directamente la función para cada una de ellas. entro de cada función de respuesta podemos procesar las órdenes Aue Aueramos. Por otro lado+ se usa send en ve- de end para enviar el resultado. Wo Aue viene a ser lo mismo+ s más o menos+ aunAue send es más fle@i"le+ admitiendo todo tipo de datos Aue son procesados para enviar al cliente la respuesta correcta. 7ampoco Cace falta esta"lecer e@plcitamente el tipo $:$E Aue se devuelve+ encargándose send del mismo. !on el mismo express se pueden generar aplicaciones no tan "ásicas e#ecutándolo de la forma siguiente9
nodemodulese@press"ine@press prue"arest *e indica el camino completo a la aplicación "inaria+ Aue sera el puesto. !on esto se genera un directorio prue"arest. !am"iándoos al mismo y
escri"iendo simplemente npm install se instalarán las dependencias necesarias. Wa aplicación estará en el ficCero appjs+ lista para funcionar+ pero evidentemente Ca"rá Aue adaptarla a nuestras necesidades particulares. El acceso a los parámetros de la llamada y la reali-ación de diferentes actividades seg,n el mismo se denomina enrutado. En e@press se pueden definir los parámetros de forma "astante simple+ usando marcadores precedidos por I. Por e#emplo+ si Aueremos tener diferentes contadores podramos usar el programa siguiente9
var e@pressYreAuireDSe@pressSFH var app Y e@pressDFH var contadores Y ne= 0rrayH var puertoYprocess.argv]2^? process.argv]2^98/8/H app.getDSS+ function DreA+ resF _ res.sendDSPortadaSFH FH app.putDScontador9idS+ functionD reA+res F _ contadores]reA.params.id^ Y /H res.sendD _ creado9 reA.params.id FH FH app.getDScontador9idS+ function DreA+ resF _ res.sendD \_ \ZreA.params.idZ\9
\Z contadores]reA.params.id^ Z \\ FH FH app.postDScontador9idS+ function DreA+ resF _ contadores]reA.params.id^ZZH res.sendD \_ \ZreA.params.idZ\9 \Z contadores]reA.params.id^ Z \\ FH FH app.listenDpuertoFH console.logDS*erver running at Cttp912'././.19SZpuertoZSSFH Este programa De@presscount.#sF introduce otras dos órdenes >E*79 P37+ Aue+ como recordamos+ sirve para crear nuevos recurso y es idempotente Dse puede usar varias veces con el mismo resultadoF+ y además P%*7. Esa orden la vamos a usar para crear contadores a los Aue posteriormente accederemos con get. P37 no es una orden a la Aue se pueda acceder desde el navegador+ as Aue para usarla necesitaremos Cacer algo as desde la lnea de órdenes9 curl FL ":? httpI//%MGG%INGNG/contador/primero
para lo Aue previamente Ca"rá Aue Ca"er instalado curl+ claro. Esta orden llama a P37 so"re el programa+ y crea un contador Aue se llama primero. 3na ve- creado+ podemos acceder a
Clientes 3E" 7ampoco es complicado escri"ir con node.#s un cliente >E*7. *e puede Cacer mediante peticiones Cttp+ pero por supuesto es más fácil escri"ir un cliente usando la li"rera restler+ Aue se instala de la misma forma Aue Cemos visto anteriormente con npm. 3na ve- instalada+ se puede escri"ir un cliente como este al utilsimo creacontadores anterior.
QRusrlocal"innode var rest Y reAuireDSrestlerSFH var url Y SCttp912'././.198/8/contadorSH process.argv.forEacCDfunction Dval+ inde@+ arrayF _ if D inde@ M 1 F _ rest.putD url Z val F.onDScompleteS+ functionD data F _ console.logD data FH FH FH
El cliente es "astante simple+ y lo Aue Cace es crear tantos contadores como argumentos le pasamos por la lnea de órdenes. 7ras definir un par de varia"les Do#o con la segunda+ tiene Aue contener el 3>W del sitio donde vamos a Cacer la consulta+ el n,mero y la dirección puede ser otro cualAuiera+ lo Aue no variará será contador si estamos usando el programa anteriorF+ usamos la varia"le processargv Aue contiene los argumentos de la lnea de órdenes. *o"re ese o"#eto e#ecutamos un "ucle+ forE*7 se usa con restput. [amos a crear un contador con el nom"re val Aue se enva desde la lnea de órdenes+ para lo Aue creamos el 3>W del mismo simplemente concatenando las dos cadenas. >ecordemos Aue node.#s act,a de forma asncrona+ por lo Aue lo Aue Cacemos con esa orden es crear un call"ac5 cuando D onF la petición se Caya completado DcompleteF. Ese call"ac5 simplemente te dice cual Ca sido la respuesta y la imprime.
*sando &ja6 0unAue inicialmente 0J0K era un acrónimo de Asynchronous Javascript and -M+ Coy en da se Ca de#ado de usar como tal y viene a a"arcar todas las tecnologas asncronas de interacción cliente servidor+ usando cualAuier formato de seriali-ación DaunAue más generalmente J*%;F y en el cliente DaunAue generalmente se trata de Java*cript+ pero puede ser tam"i
para Aue responda a un interfa- >E*7+ pero esto es simplemente una convención. Podamos+ por e#emplo+ usar los programas Aue Cemos visto anteriormente En cuanto al cliente+ Cay Aue tener en cuenta Aue ,nicamente se pueden Cacer peticiones al mismo dominio desde el Aue se Ca descargado la página en la Aue se Caya inserto. Es decir+ sólo puedes Cacer peticiones a dominiocom desde páginas Aue te Cayas descargado desde dominiocom. Por eso es importante Aue el sistema Aue tenga el 0P: >E*7 sea capa- tam"i
var fs Y reAuireDSfsSFH var e@pressYreAuireDSe@pressSFH var app Y [email protected]*erverDFH var contadores Y ne= 0rrayH var portada Y fs.read(ile*yncDSsumarformulario.CtmlS +Sutf8SFH app.getDSS+ function DreA+ resF _ res.sendDportadaFH FH app.getDS#s9pageS+ function DreA+ resF _ var #s Y fs.read(ile*yncDreA.params.pageFH
res.content7ypeDSte@t#avascriptSFH res.sendD#sFH FH app.putDScontador9idS+ functionD reA+res F _ contadores]reA.params.id^ Y /H res.sendDS!reado contador SZ reA.params.id FH FH app.postDScontador9idS+ function DreA+ resF _ contadores]reA.params.id^ZZH res.content7ypeDSapplication#sonSFH res.sendD _ resultado9 contadores]reA.params.id^ FH console.logD _ SPostS9 contadores FH FH app.getDScontador9idS+ function DreA+ resF _ res.content7ypeDSapplication#sonSFH res.sendD \_ SresultadoS9 \ Z contadores]reA.params.id^ Z \bn\ FH FH app.getDSsuma9id19id2S+ function DreA+ resF _ res.sendD _ resultado9 contadores]reA.params.id1^ Z contadores]reA.params.id2^ FH FH app.listenD8/8/FH console.logDS*erver running at Cttp912'././.198/8/SFH
Este código es similar al Aue Cemos usado anteriormente+ salvo Aue respondemos a más comandos >E*79 4E7+ P37 y P%*7. P37 crea el contador+ P%*7 lo incrementa y finalmente 4E7 o"tiene el resultadoH recordemos Aue 4E7 de"e ser idempotente y de#ar al servidor en el mismo estado. Estos dos ,ltimos+ además+ devuelven el resultado en J*%;+ y no en te@to. Wo normal sera Aue entendieran varios formatos Dincluyendo te@to y 7$WF+ pero por lo pronto lo de#aremos as. 7am"iE*7. Por eso se Ca creado otro seudo comando Aue lee un ficCero y lo sirve como J*. %#o+ este tipo de órdenes son un potencial Cueco de seguridad. Wo de#amos as por simplicidad+ no porAue sea la forma adecuada Aue de"era tener una aplicación en producción. Wa página =e" incluye =e" incluye lo mnimo necesario9 el script J* incluido y un formulario para solicitar el nom"re del contador Aue se va a incrementar. El 3>W del formulario incluye el \camino\ ficticio al Aue responderá el servidor >E*7+ Aue incluye js. Ese ficCero+ precisamente+ es el Aue vemos aAu9
function cuentaDF _ reAuest Y ne= K$Wttp>eAuestDFH
var contadorY document
.getElementy:dDScontadorSF .valueH var peticionstr Y ScontadorSZcontadorH reAuest.openDSP%*7S+ peticionstr + trueFH reAuest.onreadystatecCangeY escri"eresultado H reAuest.sendDnullFH function escri"eresultadoDF_ if D reAuest.ready*tate YY ) F _ if D reAuest.status YY 2// F _ var #sonH eval D S#son Y SZ reAuest.response7e@t FH console.logD#sonFH document.getElementy:dDS>esultadoSF. inner7$WY S>esultado Y SZ #son.resultado
Por lo pronto vemos cómo funciona en J* \clásico\+ para entender un poco me#or el mecanismo Aue sigue. Wuego más adelante veremos Aue en Juery se puede Cacer de forma mucCo más simple. El código tiene dos funciones9 la Aue Cace la llamada DcuentaF y la Aue responde a la misma+ el call"ac5 Describe_resultadoF. Wa primera construye el 3>W y Cace la petición P%*7 para incrementar el contador+ y con onreadystatechange esta"lece la llamada para cuando llegue asncronamente el resultado. Esta segunda función reci"e el J*%; y usa un simple evaluador para e@traer su resultado+ previa compro"ación de Aue efectivamente se Ca reci"ido la respuesta completa y de forma efectivaH la respuesta la escri"e en un div. Para Cacer funcionar este programa tendremos Aue crear previamente los contadores usando cualAuier otro programa En realidad+ es mucCo más fácil Cacerlo con Juery. En esta =e" de !ode5o muestran !ode5o muestran como funcionan las órdenes "ásicas. El formulario sera "astante similar+ similar+ aunAue Cemos tenido Aue modificar el servidor para Aue muestre diferentes páginas principales. principales. El principal cam"io será+ o"viamente+ en el código usado para la solicitud 0#a@+ Aue usará #uery en ve- de J* puro. elo aAu 9
VDdocumentF.readyDfunctionDF _ VD\Qformulario\F .cCangeDfunctionDF_ V.getDScontadorS ZVDSQcontadorSF.valDF+ functionD dataF _ VDSQ>esultadoSF.CtmlDS>esultado SZ data.resultadoFH FH FH FH Este peAueBo programa tiene todo lo compacto y crptico a lo Aue nos tiene acostum"rados #uery. !omo es Ca"itual+ se e#ecuta sólo cuando se Ca cargado la página y usa el programa para aBadir funcionalidad+ eventos+ al 7$W en ve- de tener el propio evento definido en el mismoH lo clásico en J* Dy #ueryF es dividir el código de la funcionalidad. Wo Aue Cace es Aue crea un evento so"re el formulario tal Aue al cam"iar llame a una función anónima. Esa función+ en un par de lneas+ Cace lo mismo Aue previamente con unas cuantas lneas en J*9 Cace una petición get Den la Aue usa tam"i
en VvalDFV+ del elemento del formularioF y una veo"tenido el resultado usa el selector del elemento correspondiente+ #5esultado+ para insertarlo. 0dicionalmente+ #uery esconde el mecanismo su"yacente de llamada CacieAuest funciona+ lo usaH si no+ usa el mecanismo nativo.
Más allá del &ja6 0#a@ permite tra"a#ar con el servidor de forma asncrona+ pero siempre Aue sea el cliente el Aue comience la cone@ión. En mucCos casos puede Aue no sea la forma más eficiente de tra"a#ar con
denominado Ge"*oc5et Aue es simplemente una cone@ión 7!P "idireccional entre cliente y servidor+ el eAuivalente en el navegador de un *oc5et tradicional. 0ctualmente no todos los navegadores admiten todos los tipos de cone@ión propuestosH se trata de un estándar en evolución Aue se Ca implementado a partir de 2/12. Para usarlo ya se puede pro"ar con li"reras como soc5et.io+ Aue proporcionan todas las facilidades de Ge"*oc5et mediante la cone@ión Aue est< disponi"le en el navegador. 3n e#emplo de como usar estas li"reras está en este tutorial Aue muestra como llevar a ca"o un cCat en tiempo real usando node.#s.
& dónde ir desde a7u( ;osotros iremos a aprender el uso de un sistema de almacenamiento de o"#etos llamado !oucC+ pero el tema de diseBo de sistemas con node.#s y #Auery en el cliente puede ir mucCo más allá+ usando+ por e#emplo marcos $[! para node.#s como *ails.#s o cualAuier otro de los recomendados. #uery tam"i
'ibliograf(a y enlaces En general+ >E*7 se considera+ de forma amplia+ dentro de los servicios Ge"+ por eso los li"ros Aue tra"a#an con E*7. *in em"argo+ si Auieres usar un lengua#e de programación determinado+ te puede venir "ien Programming Ge" *ervices =itC Perl+ de >ay y NucCen5o. Es Aui-ás un poco más proli#o en el apartado K$W de la cuenta+ y está un tanto atrasado+ pero vienen todos los módulos de Perl "ien detallados y e@plicados. El >E*7ful Ge" *ervices !oo5"oo5 tam"i
Este material está disponi"le "a#o los t
Juan J. Merelo