debug_mode=ON

Buscar en

 
 

Carga de scripts de clases bajo demanda

Escrito por lopez hace 8 meses bajo Dominio Público
766 visitas. Etiquetas: javascript, httprequest

Este es mi primer articulo aquí, así que quiero comenzar saludando a todo el mundo, así que ¡hola!

Este articulo es más que nada una "prueba de concepto". La semana pasada leí un articulo en el que explicaban la funcionalidad del atributo defer (yo sabía que existía, pero no sabía para que era), y me fijé en lo que habla del atributo async. El fin de semana he estado pensando en que eso ya tenía que ser posible a pesar de no existir el atributo, ¡¿cómo no va a ser posible, con todo lo que se puede hacer con AJAX?! Total que me he puesto (así probaba tambien eso del httpRequest que no lo había usado mas que indirectamente a través de algún api de google), y he creado un script que permite cargar otros scripts cuando necesitas crear un objeto de una clase definida en él.

Aviso: Este código es altamente mejorable, pero para lo que lo quiero es suficiente.

Archivos del ejemplo

  • La página de prueba:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Prueba de carga de scripts bajo demanda pasando argumentos al constructor</title>
    </head>
    <script type="application/javascript" src="scripts/getConstructor.js">
    </script>
    <script type="application/javascript">
    function prueba()
    {
        var elConstructor = getConstructor("Alerta", "Alerta");
        var laAlerta = new elConstructor("Esta es una prueba de la carga de archivos de script bajo demanda. Ahora debería estar cargado Alerta.js");
        laAlerta.mostrar();
        elConstructor = getConstructor("Alerta", "Mensaje")
        var elMensaje = new elConstructor();
        elConstructor = getConstructor("Alerta", "Alerta");
        var otraAlerta = new elConstructor(elMensaje.cadena);
        otraAlerta.mostrar();
        laAlerta.mostrar();
        alert(elMensaje.cadena);
    }
    
    window.onload = function ()
    {
        document.getElementById("Alerta").onclick = prueba;
    }
    </script>
    <body>
    <ul>
    <li><a href="#" id="Alerta">Cargar archivo Alerta.js</a></li>
    </ul>
    </body>
    </html>
  • El script "getConstructor.js":
    // funcion getConstructor
    // devuelve el constructor que se le indica
    function getConstructor(script, clase)
    {
        var constructor;
        try{
            constructor = eval(clase);
        }catch(e)
        {
            constructor = recuperarConstructor(script, clase);
            window[clase] = constructor;
        }
        return constructor;
    }
    
    function recuperarConstructor(script, clase)
    {
        var elScript = recuperarScript(script);
        var constructor = eval(elScript + "\n" + clase + ";");
        alert("cargado clase");
        return constructor;
    }
    
    var _losScripts = [];
    function recuperarScript(script)
    {
        var elScript = "";
    
        if( _losScripts[script])
        {
            elScript = _losScripts[script];
        }
        else
        {
            var elHttpRequest = getHttpRequest();
            if(elHttpRequest)
            {
                elHttpRequest.overrideMimeType("application/javascript");
                elHttpRequest.open("GET", "scripts/clases/" + script + ".js", false);
                elHttpRequest.send(null);
                if(elHttpRequest.status == 200)
                {
                    elScript = elHttpRequest.responseText;
                    _losScripts[script] = elScript;
                    alert("cargado script");
                }
                else
                {
                    alert("No se ha podido cargar la clase '" + clase + "': " + elHttpRequest.statusText);
                }
            }
        }
        return elScript;
    }
    
    //Sacado de http://es.wikipedia.org/wiki/XMLHttpRequest 
    function getHttpRequest()
    {
        var httpRequest;
        if (window.XMLHttpRequest)
        {
            httpRequest = new XMLHttpRequest();
        } 
        else if (window.ActiveXObject)
        {
            try {
                httpRequest = new ActiveXObject("MSXML2.XMLHTTP");
            } catch (e) {
                try {
                    httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e) {
                    httpRequest = false;
                }
            }
        }
        return httpRequest;
    }
  • Y un script para las pruebas:
    // Clase Alerta y Clase Mensaje
    
    function Mensaje()
    {
        this.cadena = "Mensaje encerrando en una clase.";
    }
    
    function Alerta(elMensaje)
    {
        this.mensaje = elMensaje || "";
    }
    
    Alerta.prototype.mostrar =  function ()
    {
        alert(this.mensaje);
    }

Pequeña explicación

Digo pequeña porque lo que hace creo que se ve bien, si no tiene el script ya cargado lo carga mediante XMLHttpRequest a continuación saca el constructor de la clase y lo hace accesible para su próximo uso. Lo que si me gustaría explicar es el porque he hecho estas cosas como las he hecho, por si alguien tiene alguna solución mejor:

  • Al llamar al método open del objeto httpRequest, le paso en el tercer parámetro false para que sea una llamada síncrona, ya que no tiene sentido que el método siga hasta que esté cargado el archivo. Sin embargo, supongo que también se podría hacer con una llamada asíncrona, pero no le veo la utilidad. Hasta que no tienes el script no puedes crear el objeto, y por lo tanto no sirve de nada que el script continúe.
  • Para obtener el constructor de un script añado el nombre de la clase antes de evaluarlo. Esto lo hago porque eval se ejecuta "en otro sitio", el objeto padre no es window por lo que no basta con evaluar un script para que lo que en el se defina se añada al entorno de ejecución. Debido a que eval devuelve el resultado de lo que evalúa añado el nombre de la clase, para que lo último que evalúe (y por tanto, lo que devuelva) sea el constructor.
  • Una vez obtenido el constructor lo añado a window por lo explicado en el punto anterior.

Esto es todo, espero que a alguien le sea de utilidad o le resulte interesante.

Un saludo.

 

¡Votalo! 3 votos
¡Compártelo!

        

&nbps;

&nbps;

lopez

Sobre lopez

Este usuario no ha completado su perfil.

 
Regístrate o haz login para participar.
¿Todavía no conoces debugmodeon?
debugmodeon es la red social para profesionales de la informática
descubre debugmodeon
 

6 comentarios en "Carga de scripts de clases bajo demanda"

jsanca
jsanca escribió
hace 8 meses

#1   

Un tema particular y relacionado, es la carga de JavaScript.
Segun he leido, los script se cargan sincronicamente, es decir el browser no descarga nada mas hasta que no se encuentre bajado y procesado el javascript, por lo tanto los javascript deben ser procesados una vez que la pagina este cargada.

Yahoo UI ofrece el componente GET para realizar ese trabajo, adicionalmente puedes utilizarlo con el evento onDomReady para meter los scripts en esta parte.

UN saludo,
J

 

lopez
lopez escribió
hace 8 meses

#2   

Hola,

hasta donde yo se (que puedo estar equivocado), los navegadores cargan múltiples archivos en paralelo (creo que hasta 4 por cada dominio) independientemente de si son scripts, imágenes, archivos css, etc. Otra cosa es que después se carguen secuencialmente.

He mirado lo del método get y parece que sí que hace esto (aunque lo hará mejor). Por la explicación parece que lo carga y lo ejecuta, aunque he mirado un poco por encima el script, pero no veo como lo ejecuta. Lo miraré con mas atención en otro momento.

Gracias por el comentario, un saludo

 

jsanca
jsanca escribió
hace 8 meses

#3   

Lo del sincronismo del javascript fue algo que aprendi hace poco, de hecho esa fue la razon por la que di con el metodo GET

 

csalazart
csalazart escribió
hace 8 meses

#4   

Pues la Libraria Prototype tiene unos metodos parecidos y ofrece un servicio similar asi como si se junta con la mootools y jquery .. ahora bien
tebngo entendido que si se cargan paginas o archivos que contengan jscripts estos no se ejecutan amenos se que llame una funcion evalscripts aun no he visto bien esa parte pero se que algo de eso he visto por ahi creo que funciona bien es con prototype que lo estuve revisando aunque no he visto del todo la libraria pusto que apenas la estoy revisnadoo.

 

lopez
lopez escribió
hace 8 meses

#5   

Efectivamente, tanto en prototype (ver punto 8 "Funciones para AJAX") como en jquery (ver punto 4 "Funciones para AJAX") hay maneras de hacer esto mismo y seguramente se hará mejor. No he hecho nada con AJAX de verdad, pero era mas que nada una prueba de que es posible hacerlo, y de como se podría hacer.

Un saludo.

 

csalazart
csalazart escribió
hace 8 meses

#6   

claro nada mejor que a la antiguita.. hahaha :P eso tambien VALE!!

 
 
 
 

© Copyright 2008-2009 debug_mode=ON | Aviso legal | Contacto | FAQ | ¿Quiénes somos? |