Desarrollo de sitios web fácil y en tiempo real con Meteor

Implementación rápida de aplicaciones basadas en datos que responden de forma casi instantánea a la interacción del usuario

Debido a la ubicuidad de la web, hasta los menores retardos en la entrega de datos resulta irritante para los usuarios. Quieren que los datos se actualicen de forma inmediata. Desafortunadamente, la tecnología web aun no ha podido afrontar totalmente esta demanda de acceso en tiempo real. Si bien el acceso a los datos se está estandarizando rápidamente en varias clases de Object-Relational Mapping (ORM), la comunicación en tiempo real no tiene esa solución. Este artículo habla sobre Meteor, una nueva y fascinante infraestructura de JavaScript que tiene como objetivo resolver este problema.

David Berube, Propietario, Berube Consulting

David BerubeDavid Berube es consultor, disertante y autor de Practical Rails Plugins, Practical Reporting with Ruby and Railsy Practical Ruby Gems. También escribió para diversas revistas, entre ellas: Dr. Dobb's Journal y Linux Pro Magazine. Se dedica al desarrollo de software y a la consultoría de desempeño para numerosos clientes e industrias.



06-05-2013

¿Qué Es Meteor?

Meteor es una nueva infraestructura de JavaScript que tiene como objetivo automatizar y simplificar el desarrollo de aplicaciones web que actúan en tiempo real. Usa la comunicación en tiempo real mediante un protocolo llamado Distributed Data Protocol (DDP), que es admitido en navegadores nuevos que usan WebSockets o en navegadores anteriores que usan Asynchronous JavaScript + XML (Ajax) long polling. En ambos casos, la comunicación navegador-servidor es transparente.

El protocolo DDP está diseñado para trabajar con colecciones de documentos JavaScript Serialized Object Notation (JSON), facilitando la creación, actualización, eliminación, consulta y, por supuesto, visualización de documentos JSON. Como DDP es un protocolo de código abierto, se puede conectar con cualquier cliente o almacén de datos. La novedad es que funciona con MongoDB.

De hecho, Meteor proporciona dos bases de datos: una base de datos caché del lado del cliente y una base de datos MongoDB en el servidor. Cuando un usuario modifica algún dato—haciendo clic en Save, por ejemplo,—el código JavaScript que se ejecuta en el navegador actualiza la entrada correspondiente de la base de datos en MongoDB local y luego realiza una solicitud de DDP al servidor. El código actúa de inmediato como si la operación hubiera sido exitosa porque no necesita esperar la respuesta por el servidor. Mientras tanto, el servidor se actualiza en segundo plano. Si se produce un error en la operación del servidor o si devuelve un resultado inesperado, el código JavaScript del lado del cliente se reajusta inmediatamente según los datos devueltos recientemente del servidor. Este ajuste se denomina compensación de latencia y genera una cantidad de velocidad adicional que el usuario percibe.

Incluso el sistema de plantillas de Meteor está diseñado específicamente para facilitar la comunicación en tiempo real. En la mayoría de las infraestructuras web, es posible combinar fácilmente lenguaje de marcado de hipertexto (HTML)—u otro lenguaje de marcado equivalente a HTML, como HTML Abstraction Markup Language (Haml)—con código. Esto permite insertar fácilmente valores dinámicos de la base de datos en páginas que se envían al usuario. Después de eso, uno es responsable de colocar el sistema en su lugar para observar los cambios en los datos y luego actualizar la marcación. El sistema de plantillas de Meteor, sin embargo, está diseñado para grabar a qué datos se accede desde una plantilla y para configurar automáticamente devoluciones de llamadas para cambiar ese HTML cuando se modifican los datos subyacentes, haciendo que las plantillas en tiempo real sean más simples y rápidas.


Ejemplo: competencia de popularidad de enlaces

La funcionalidad de las plantillas de Meteor puede hacer que sea más fácil escribir una gran variedad de aplicaciones. Por ejemplo, suponiendo que desea crear un sitio donde los usuarios puedan introducir enlaces—es decir, localizadores universales de recursos (URLs)—y darles una puntuación, con los URLs que ganan la competencia de popularidad ubicados en los primeros lugares de una lista. Con Meteor, puede escribir fácilmente esa aplicación para que los usuarios vean los 65 votos de otros usuarios en tiempo real.


Instalación de Meteor

Para instalar Meteor, escriba el código que se muestra en un terminal X Listado 1 del SO Linux® o Mac® . Meteor no es compatible con Microsoft® Windows®.

Listado 1. Cómo instalar Meteor
curl https://install.meteor.com > install_meteor.sh
chmod u+x install_meteor.sh
./install_meteor.sh

Ahora, puede crear un proyecto nuevo.


Creación de un proyecto nuevo

El comando meteor automatiza el proceso de creación de un proyecto nuevo con todo lo que Meteor necesita para su operación. Escriba los comandos que se muestran en el Listado 2 para crear un proyecto llamado realtime_links.

Listado 2. Cómo crear un proyecto nuevo en Meteor
meteor realtime_links
cd realtime_links

Meteor crea un directorio que contiene un archivo HTML, un archivo JavaScript, y un archivo de hoja de estilo en cascada (CSS). El último es un archivo CSS estándar, pero vale la pena discutir sobre los primeros dos. Se pueden descargar las versiones completas de los archivos realtime_links.html y realtime_links.js desde Download .


Archivo realtime_links.html

Listado 3 muestra la cabecera y fragmentos del cuerpo del archivo realtime_links.html.

Listado 3. Cabecera y fragmentos del cuerpo de realtime_links.html
<head>
<title>Realtime Links Demo</title>
</head>

<body>
  {{> header }}
  {{> link_list }}
  {{> add_new_link }}
</body>

Como puede ver, el comienzo de la plantilla HTML es directo. No es necesario preocuparse por incluir etiquetas BODY , declaraciones DOCTYPE ni archivos JavaScript o CSS. Meteor se encarga de todo eso. Para obtener más información sobre la unión de archivos JavaScript y CSS en Meteor, consulte Recursos y siga el enlace al sitio web de Meteor.

La sintaxis {{> significa "representar esta plantilla". Como se muestra, realtime_links.html representa tres plantillas:

  • header es una simple cabecera que muestra el número de enlaces en la base de datos.
  • link_list muestra la lista de enlaces y los votos asociados a ellos.
  • add_new_link es una forma de añadir enlaces nuevos.

Listado 4 muestra la plantilla header .

Listado 4. Plantilla realtime_links.html header
<template name="header">


<h1>The Link Collection</h1>

	<p>We currently have {{collection_size}} links.</p>

</template>

La plantilla header representa simplemente una etiqueta h1 y una breve descripción del tamaño de la colección. El método collection_size está definido en el archivo JavaScript, realtime_links.js (que abordaremos en la sección siguiente). Meteor observa automáticamente qué partes de datos son incorporados por la plantilla. Entonces, cuando se actualiza el tamaño de la colección, la plantilla header se actualiza automáticamente.

Observe que la sintaxis {{ ... } que se utiliza aquí es similar a <%= ... %> de Ruby en Rails o a <?= ... ?> en PHP. Puede interpolar código arbitrario, de modo que puede insertar cualquier expresión dinámica útil de esa manera.

Listado 5 muestra la plantilla link_list .

Listado 5. Plantilla realtime_links.html link_list
<template name=
"link_list">

  <ul>

    {{#each links }}

      <li>  {{> link_detail }} </li>

    {{/each }}

  </ul>

</template>

Como puede ver, el código que se muestra en Listado 5 es una lista de enlaces. El método links del archivo realtime_links.js JavaScript proporciona esta lista. La plantilla link_detail representa cada enlace. Tenga en cuenta que no es necesario pasar ningún argumento porque los bucles #each de Handlebars establecen el contexto actual para que cada iteración sea el objeto actual. En otras palabras, los métodos locales de la plantilla link_detail se interpretan correctamente como métodos de cada objeto de enlace.

Listado 6 muestra la plantilla link_detail , que controla los datos que se muestran para cada enlace individual.

Listado 6. Plantilla realtime_links.html link_detail
<template name="link_detail">


<div id="link-{{id}}">

    <h1>{{url}}</h1>

    <p><strong>Stats:</strong> up: {{thumbs_up}} down: {{thumbs_down}} 
net score: {{score}}</p>


<input type="button" value="Thumbs Up" 
 class="thumbs_up" url="{{url}}" />
    <input type="button" value="Thumbs Down" 
class="thumbs_down" url="{{url}}" />


</div>

</template>

El elemento h1 simplemente muestra el URL del enlace actual. Luego, hay un breve listado de estadísticas que incluye la cantidad de votos positivos y negativos que obtuvo un enlace y su puntuación en la red, que resulta de la diferencia entre los dos valores. Finalmente, hay dos botones: uno de pulgar hacia arriba, o voto positivo, y uno de pulgar hacia abajo, o voto negativo. El archivo JavaScript define el comportamiento de estos botones, pero existe una plantilla más que debemos examinar antes de profundizar en esto.

Listado 7 muestra la plantilla add_new_link .

Listado 7. Plantilla realtime_links.html add_new_link
<template name="add_new_link">

  <div id="new_link_form">

    URL: <input id="url">

<input type="button" value="Click" id="add_url" />

  </div>

</template>

Esta plantilla consta simplemente de un campo de entrada de texto y un botón, que en conjunto forman la interfaz para añadir nuevos URLs a la lista.


Archivo realtime_links.js

El código JavaScript de realtime_links.js controla el acceso a los datos y las devoluciones de llamadas de eventos desde su programa, tanto del lado del cliente como del servidor. La sentencia if (Meteor.is_client) marca la parte del lado del cliente y la sentencia if (Meteor.is_server) marca el lado del servidor. Meteor ofrece una forma de proteger el código sensible para que los clientes malintencionados no puedan ver el código abierto. Consulte el enlace a la documentación de Meteor en la sección Recursos para conocer más detalles.

Listado 8 muestra la cabecera y las funciones del ayudante de la lista de enlaces.

Listado 8. Cabecera y funciones del ayudante de la lista de enlaces
Template.header.collection_size = function () {
return Links.find({}).count();
	};


	Template.link_list.links = function () {
return Links.find({}, {sort : {score: -1} });
	};

La plantilla header utiliza la primera función del ayudante del listado, que simplemente devuelve el tamaño de la colección de links . La plantilla link_list utiliza la función del segundo ayudante, que devuelve todos los enlaces ordenados por la puntación más alta a la más baja.

Listado 9 tiene dos devoluciones de llamadas de eventos para la plantilla link_detail .

Listado 9. Devoluciones de llamadas de eventos link_detail
	Template.link_detail.events = 
{

'click input.thumbs_up' : function () {
Meteor.call('vote', this.url, 'thumbs_up');
},

  'click input.thumbs_down' : function 
() {Meteor.call('vote', this.url, 'thumbs_down');}

	};

Cada devolución de llamada se encarga de un evento de clic de voto positivo o negativo. En ambos casos, usan Meteor.call del lado del cliente para realizar una llamada de función del lado del servidor. Como puede ver, hacer llamadas desde el lado del cliente al servidor es fácil. Por ejemplo, la serialización se administra automáticamente.

Listado 10 muestra la devolución de llamada del evento para el formulario donde los usuarios pueden añadir más enlaces.

Listado 10. Llamada de devolución de evento para formulario de nuevos enlaces
  Template.add_new_link.events = {

    'click input#add_url' : 
dfunction () {

var new_url = $('#url').val();

      var url_row = Links.findOne( {url:new_url} );

      if(!url_row){

Links.insert( { url : new_url,
score: 0,
thumbs_up: 0,

thumbs_down: 0 });
      }
Meteor.call('vote', url, 'thumbs_up');

    }
  };

Primero, el formulario intenta localizar un objeto de enlace existente del URL solicitado. Si encuentra uno, cuenta la solicitud como un voto para el objeto de enlace existente. Si no encuentra ninguno, crea un objeto de enlace nuevo y hace un voto thumbs_up para ese objeto nuevo.

Esta parte del código ilustra tanto las ventajas como las limitaciones de Meteor como tecnología de vanguardia que aun no está prevista para uso de producción. Como puede ver, el cliente puede simplemente llamar a insert en la colección links . Si bien resulta útil para el desarrollador, todavía existen algunos problemas desde el punto de vista de la seguridad. Afortunadamente, los desarrolladores están trabajando activamente en una parte auth del código que implementa eficientes funciones de autenticación al mismo tiempo que preserva gran parte de la potencia y flexibilidad que hacen que Meteor sea tan atractivo.

Además, tenga presente que Meteor actualmente no implementa todas las funciones de MongoDB. Por ejemplo, Meteor no admite inserciones ni actualizaciones de MongoDB, que insertan datos nuevos o modifican los existentes. Si Meteor admitiera inserciones y actualizaciones, se podría escribir la función que se muestra en Listado 11.

Listado 11. Devolución de llamada de evento hipotética con inserción y actualización para adición de formulario de enlace nuevo
  Template.add_new_link.events = {

    'click input#add_url' : function () {

      var new_url = $('#url').val();

       Links.update( { url : new_url}, 
                     { $set: {url : new_url}, 
                       $inc: { votes : 1 } } , true );


    }
  };

Como puede ver, el código es más corto si se usan inserciones y actualizaciones. Probablemente, también sería más rápido, ya que solo requiere solo la ida al servidor. Con suerte, Meteor pronto implementará la compatibilidad con inserciones y actualizaciones, y otras funciones nuevas.

El código del Listado 12 se ejecuta en el servidor. Es un método único que puede ser llamado por el código del lado del cliente. Este método, vote, le permite al cliente votar thumbs_up o thumbs_down en un URL particular. Usa el operador $inc de Mongo para incrementar el contador de votos correspondiente. También incrementa o disminuye la puntuación total según sea necesario. El método Meteor.startup permite que el código se ejecute solamente cuando se inicializa el servidor. La función Meteor.methods luego define las funciones que se pueden llamar del lado del cliente utilizando Meteor.call, tal como se mostró anteriormente en Listado 9.

Listado 12. Código para el métodovote del lado del servidor.
if (Meteor.is_server) {
    Meteor.startup(function () {
      Meteor.methods({
        vote: function (url, field){

new_obj = { $inc: { } };

 if(field =='thumbs_up'){
new_obj['$inc']['thumbs_up'] = 1;
 new_obj['$inc']['score'] = 1;
 }else{
new_obj['$inc']['thumbs_down'] = 1;
 new_obj['$inc']['score'] = -1;
                }

                Links.update( { url : url}, new_obj );

              }
      });
    });
}

Del mismo modo que en Listado 10, se puede ejecutar el código de Listado 12 del lado del cliente. Sin embargo, para fines ilustrativos, se ejecuta del lado del servidor. A medida que el modelo de seguridad de Meteor progresa, es probable que el código sensible se desarrolle como funciones del lado del servidor, como se muestra en este listado.


Aplicación en acción

En este punto, puede iniciar la aplicación, como se muestra en Listado 13, y verla en funcionamiento.

Listado 13. Cómo iniciar el sistema
meteor

Después de inicializar, Meteor se ejecuta en el puerto 3000. Abra un navegador web y vaya a http://localhost:3000/.

Si añade un URL en Add a URL y hace clic en Add, debe aparecer un URL con una puntuación de uno. A continuación, puede hacer clic en el botón Thumbs Up o Thumbs Down para votar a favor o en contra del URL. Esto ocurre en tiempo real sin actualizaciones en la página. Si abre un navegador web, puede hacer lo mismo en otra ventana mientras que los cambios se reflejan de forma instantánea en la primera ventana.

Cuando se añaden varios URLs, se puede observar que el que tiene la puntuación más alta—se define como puntuación a la diferencia entre votos positivos y negativos —aparece en el primer lugar. A medida que se realizan los votos positivos y negativos, los URLs suben o bajan en la lista debido a que cambian sus puntuaciones. Esto ocurre en tiempo real con múltiples usuarios en múltiples navegadores que reciben los mismos datos a medida que se realizan los votos.


Conclusión

Meteor es una infraestructura web de vanguardia que contiene muchos conceptos interesantes. Su compatibilidad con los datos en tiempo real es a la vez atractiva e importante, especialmente si se tiene en cuenta que en otras tecnologías la compatibilidad con los datos en tiempo real es, como mucho, una simple idea. Mientras que la interacción en tiempo real se vuelve cada vez más importante para el futuro de la Web, lo mismo ocurre con la capacidad de Meteor para trabajar de forma fácil y rápida con conjuntos de datos complejos en tiempo real.


Descargar

DescripciónNombretamaño
Example source code for this articlerealtime_links.zip2KB

Recursos

Aprender

Obtener los productos y tecnologías

Comentar

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=SOA y servicios web
ArticleID=928865
ArticleTitle=Desarrollo de sitios web fácil y en tiempo real con Meteor
publish-date=05062013