2011-12-20 8 views
43

¿Cómo puedo insertar un elemento <script src="https://remote.com/"></script> en mi página, esperar a que se ejecute y luego usar las funciones que define?Inyectar una etiqueta de script con src remoto y esperar a que se ejecute

FYI: en mi caso, el script hará un procesamiento de tarjeta de crédito en casos excepcionales, por lo que no quiero incluirlo siempre. Quiero incluirlo rápidamente cuando el usuario abre un cuadro de diálogo cambiar opciones de tarjeta de crédito y luego enviarle las nuevas opciones de tarjeta de crédito.

Editar para obtener detalles adicionales: No tengo acceso a la secuencia de comandos remota.

+0

¿Tiene control sobre el script remoto? Si es así, puede ser más fácil hacer que el script llame a su código cuando esté hecho, a-la JSONP – hugomg

+0

Lamentablemente no tengo control sobre el script remoto. Editando la pregunta para reflejar que ~ –

Respuesta

81

Se puede usar Google Analytics o método Facebook 's:

(function(d, script) { 
    script = d.createElement('script'); 
    script.type = 'text/javascript'; 
    script.async = true; 
    script.onload = function(){ 
     // remote script has loaded 
    }; 
    script.src = 'http://www.google-analytics.com/ga.js'; 
    d.getElementsByTagName('head')[0].appendChild(script); 
}(document)); 

ACTUALIZACIÓN:

A continuación se muestra el nuevo método de Facebook; que se basa en una etiqueta de secuencia de comandos existente en lugar de <head>:

(function(d, s, id){ 
    var js, fjs = d.getElementsByTagName(s)[0]; 
    if (d.getElementById(id)){ return; } 
    js = d.createElement(s); js.id = id; 
    js.onload = function(){ 
     // remote script has loaded 
    }; 
    js.src = "//connect.facebook.net/en_US/sdk.js"; 
    fjs.parentNode.insertBefore(js, fjs); 
}(document, 'script', 'facebook-jssdk')); 
  • Reemplazar facebook-jssdk con su identificador único de la escritura para evitar que se añade más de una vez.
  • Reemplace la URL del script con la suya.
+0

Esto parece perfecto, pero hay un poco de charla en Internet que onload no es llamado por todos los navegadores. ¿Sabes con qué navegadores funcionaría? –

+4

Ver http://msdn.microsoft.com/en-us/library/hh180173(v=vs.85).aspx. – Seth

+0

¿Por qué no anexas esto al cuerpo? –

5

algo como esto debe hacer el truco:

(function() { 
    // Create a new script node 
    var script = document.createElement("script"); 
    script.type = "text/javascript"; 
    script.onload = function() { 
     // Cleanup onload handler 
     script.onload = null; 

     // do stuff with the loaded script! 

    } 

    // Add the script to the DOM 
    (document.getElementsByTagName("head")[ 0 ]).appendChild(script); 

    // Set the `src` to begin transport 
    script.src = "https://remote.com/"; 
})(); 

espero que ayude! aclamaciones.

+0

¿Hay alguna razón por la que establezca manualmente la secuencia de comandos onload para null en la devolución de llamada?¿Hay algún problema con que se active más de una vez, o solo está forzando algún tipo de recolección de basura? –

+0

Sí, eso es para evitar fugas de memoria en IE antiguo, debido al elemento de script que hace referencia a una función como el controlador de carga. – keeganwatkins

14

método utilizando detectores de eventos mismos y ES2015 construye:

function injectScript(src) { 
    return new Promise((resolve, reject) => { 
     const script = document.createElement('script'); 
     script.async = true; 
     script.src = src; 
     script.addEventListener('load', resolve); 
     script.addEventListener('error',() => reject('Error loading script.')); 
     script.addEventListener('abort',() => reject('Script loading aborted.')); 
     document.head.appendChild(script); 
    }); 
} 

injectScript('http://example.com/script.js') 
    .then(() => { 
     console.log('Script loaded!'); 
    }).catch(error => { 
     console.log(error); 
    }); 
4

Esta es una manera de cargar y ejecutar una lista de secuencias de comandos sincrónicamente dinámicamente. Es necesario insertar cada etiqueta de script en el DOM, establecer explícitamente su atributo async en false:

script.async = false; 

secuencias de comandos que han sido inyectados en el DOM se ejecutan de forma asíncrona por defecto, así que hay que establecer el atributo async en false manualmente para solucionar esto.

Ejemplo

<script> 
(function() { 
    var scriptNames = [ 
    "https://code.jquery.com/jquery.min.js", 
    "example.js" 
    ]; 
    for (var i = 0; i < scriptNames.length; i++) { 
    var script = document.createElement('script'); 
    script.src = scriptNames[i]; 
    script.async = false; // This is required for synchronous execution 
    document.head.appendChild(script); 
    } 
    // jquery.min.js and example.js will be run in order and synchronously 
})(); 
</script> 

<!-- Gotcha: these two script tags may still be run before `jquery.min.js` 
    and `example.js` --> 
<script src="example2.js"></script> 
<script>/* ... */<script> 

Referencias

+0

Está funcionando ahora, upvoted. Por cierto, al último script de cierre le falta la barra diagonal inversa. –

Cuestiones relacionadas