Javascript No Obstrusivo o cuando Ajax es un problema

Posted by joahking Thu, 24 Apr 2008 09:52:47 GMT

Ajax ha sido un boom en el desarrollo web en los últimos tiempos, es un hecho.

Pero no es una alfombra mágica, y mal usado puede crear problemas de rendimiento. Puedes probar una busqueda en Google, pero los puntos problematicos son estos más o menos:

Por ejemplo, los Cascade Selects que me han regalado en Navidad mejorarían el rendimiento si mandara a la vista todos los datos necesarios y construir los selects usando OPTGROUP y no pedir pequeñas cantidades por Ajax cada vez que elijo Galicia en vez de Murcia.

Esto es precisamente lo que intenta resolver el nunca suficientemente alabado Ryan Bates en su railscast Dynamic Select Menus. Su idea es en la vista pedirle js a un javascript controller:

<!-- views/somethings/new.html.erb -->
   <% javascript 'esta_accion' %>

# application_helper.rb
def javascript(*files)
  content_for(:head) { javascript_include_tag(*files) }
end

# y en el javascript_controller
def esta_accion
  @datos = Dato.find :all
end

Luego el erb parseará el views/javascripts/esta_accion.js.erb que se encargará de generarnos un javascript a la medida.

Hasta aquí todo bien, pero si lo miramos con el tipo de ojo correcto esto no nos resuelve el problema completamente. Mirando los logs notamos que para generar la vista new de los somethings estamos haciéndole dos peticiones al Rails.

Fíjate que este dos es una palabra maleta: no solo lleva dentro otra petición Rails (¡petición es otra palabra maleta!), sino y esto es peor: si el proceso es más complejo que mis simples selects estaré repitiendo código del negocio de la acción new de Something en otro controller (oh Dios! dira el Pana, unDRY code! y saldrá corriendo a desinfectarse las manos).

O sea que eliminamos los muchos accesos al DOM y el Ajax pero a muy mal precio, ¿porqué no reducimos el round-trip a solo una request?

¡Que entre Unobstrusive Javascript !

no voy a extenderme diciendo qué es el Javascript No Obstrusivo, para eso están los gurus y Mr. Google.

Resumiendo la idea es sacar el javascript del html y pegarle eventos a los elementos desde un javascript después que la página esté cargada:


<!-- algún html define el elemento -->
   <button id="alertable">Click me!</button>

<!-- algún javascript le pega el evento onclick -->
  document.observe(
     "dom:ready", 
     function() {
         document.getElementById("alertable").addEventListener( 'click',
            function() { 
               alert("Gracias, he esperado toda mi vida este momento!"); 
            }, 
         false);
      });
Hay un screencast muy bueno en railsenvy sobre cómo integrar UJS en Rails. Quedaría así resumiendo:

<!-- en el layout -->
<head>
    <%= yield :unobstrusive_javascript %>
</head>

<!-- views/algos/show.html.erb -->
<% content_for :unobtrusive_javascript do -%>
  <script type="text/javascript" charset="utf-8">
    document.observe(
        "dom:ready", 
        arrancaUserInterface('<%= @datos_para_la_UI.to_json %>'), 
        false
    );
  </script>
<% end %>

Wow! Gracias Jason, ya no necesitamos más el javascripts_controller, estoy contento con esta solución pero igual me falta la elegancia de la solución anterior, donde no tenía javascript en el head de mi html, sino en un hermoso esta_accion.js.

Talvez UJS4Rails es lo que estoy buscando, pero…

Si este fuera el mejor de los mundos posibles ¿cómo querría que esto quedara?

Me gustaría que en el procesamiento MVC de la petición Rails transformara la V en V + js, así tendriamos unobstrusive js out of the box, REST y algunas otras golosinas. Pero quien sabe si Rails Edge….

Comments

  1. Avatar joahking said 1 day later:

    a este habria que darle una oportunidad

    http://agilewebdevelopment.com/plugins/cascading_javascripts

    carga en el javascript_include_tag macro los archivos javascript siguientes (si existen) en este orden:

    1. application.js; and
    2. #{controller_name/action_name}.js (ej. home/index.js, customers/new.js, etc).
    This comment has been flagged for moderator approval. It won't appear on this blog until the author approves it.

(leave url/email »)

   Comment Markup Help Preview comment