Cómo saber si una etiqueta <script> no se pudo cargar


111

Estoy agregando <script>etiquetas dinámicamente a una página <head>, y me gustaría poder saber si la carga falló de alguna manera: un 404, un error de secuencia de comandos en la secuencia de comandos cargada, lo que sea.

En Firefox, esto funciona:

var script_tag = document.createElement('script');
script_tag.setAttribute('type', 'text/javascript');
script_tag.setAttribute('src', 'http://fail.org/nonexistant.js');
script_tag.onerror = function() { alert("Loading failed!"); }
document.getElementsByTagName('head')[0].appendChild(script_tag);

Sin embargo, esto no funciona en IE o Safari.

¿Alguien conoce alguna forma de hacer que esto funcione en navegadores distintos a Firefox?

(No creo que una solución que requiera colocar un código especial dentro de los archivos .js sea buena. Es poco elegante e inflexible).


4
Gran sitio web, carga automática de dependencias para contenido cargado a través de ajax. if+ el sondeo es un problema molesto que no quiero tener que poner en todo JS.
David

2
También puede ser que desee comprobar si hay fallo de la carga al hacer una solicitud JSONP mediante inyección etiqueta script ...
schellsan

Respuestas:


36

No hay ningún evento de error para la etiqueta de secuencia de comandos. Puede saber cuándo tiene éxito y asumir que no se ha cargado después de un tiempo de espera:

<script type="text/javascript" onload="loaded=1" src="....js"></script>

7
El oyente "onload" se activará incluso si hay un error de JavaScript.
Luca Matteis

38
Bueno, sí, si el archivo se CARGA y hay un error en el archivo en sí, pero si el archivo no se entrega, la carga nunca se activará.
Diodeus - James MacFarlane

1
sí, es cierto, por eso pedí ser más específico sobre qué tipo de error está buscando.
Luca Matteis

1
Pero el tiempo de espera debe ser proporcionado por el codificador de la página, ¿verdad? Por lo tanto, el codificador puede elegir un tiempo de espera diferente para el navegador, asumir que la carga de la secuencia de comandos se agotó y luego hacer que se ejecute correctamente un poco más tarde. ¿O no?
hippietrail

6
Hay un error evnt para la etiqueta de script. Se disparará cuando no se encuentre el recurso.
Nguyen Tran

24

Si solo le interesan los navegadores html5, puede usar el evento de error (ya que esto es solo para el manejo de errores, debería estar bien admitir esto solo en los navegadores de próxima generación para KISS en mi humilde opinión).

De la especificación:

Si el valor del atributo src es la cadena vacía o si no se pudo resolver, entonces el agente de usuario debe poner en cola una tarea para disparar un evento simple llamado error en el elemento y cancelar estos pasos.

~

Si la carga resultó en un error (por ejemplo, un error de DNS o un error HTTP 404), la ejecución del bloque de script debe consistir en disparar un evento simple llamado error en el elemento.

Esto significa que no tiene que realizar ningún sondeo propenso a errores y puede combinarlo con el atributo async y defer para asegurarse de que el script no esté bloqueando la representación de la página:

El atributo diferir puede especificarse incluso si se especifica el atributo asíncrono, para hacer que los navegadores web heredados que solo admiten diferir (y no asíncrono) recurran al comportamiento diferido en lugar del comportamiento de bloqueo síncrono que es el predeterminado.

Más en http://www.w3.org/TR/html5/scripting-1.html#script


1
¿Alguna idea de implementaciones JSONP, como esa en jQuery, es compatible con esto? Todo lo que he leído aquí sobre la detección de fallas de carga de JSONP dice que no se puede detectar, pero un tiempo de espera puede ser una solución alternativa, y se agregó un tiempo de espera a una versión reciente de JSONP. Sin embargo, parece que esta respuesta proporciona algo mejor que el tiempo de espera, ¿es correcto?
hippietrail

1
ejemplo posible por favor?
rogerdpack

13
<script src="nonexistent.js" onerror="alert('error!')"></script> violín
Rudey

@Rudey Uncaught SyntaxError: Unexpected token '<'(en la última versión de Chrome)
daleyjem

@daleyjem parece que ha intentado poner una etiqueta HTML en JavaScript. <script src="nonexistent.js" onerror="alert('error!')"></script>debe ir en su archivo HTML, no en JS.
Rudey

21

El guión de Erwinus funciona muy bien, pero no está codificado con mucha claridad. Me tomé la libertad de limpiarlo y descifrar lo que estaba haciendo. Hice estos cambios:

  • Nombres de variables significativos
  • Uso de prototype.
  • require() usa una variable de argumento
  • No alert()se devuelven mensajes de forma predeterminada
  • Se corrigieron algunos errores de sintaxis y problemas de alcance que estaba recibiendo

Gracias de nuevo a Erwinus, la funcionalidad en sí es perfecta.

function ScriptLoader() {
}

ScriptLoader.prototype = {

    timer: function (times, // number of times to try
                     delay, // delay per try
                     delayMore, // extra delay per try (additional to delay)
                     test, // called each try, timer stops if this returns true
                     failure, // called on failure
                     result // used internally, shouldn't be passed
            ) {
        var me = this;
        if (times == -1 || times > 0) {
            setTimeout(function () {
                result = (test()) ? 1 : 0;
                me.timer((result) ? 0 : (times > 0) ? --times : times, delay + ((delayMore) ? delayMore : 0), delayMore, test, failure, result);
            }, (result || delay < 0) ? 0.1 : delay);
        } else if (typeof failure == 'function') {
            setTimeout(failure, 1);
        }
    },

    addEvent: function (el, eventName, eventFunc) {
        if (typeof el != 'object') {
            return false;
        }

        if (el.addEventListener) {
            el.addEventListener(eventName, eventFunc, false);
            return true;
        }

        if (el.attachEvent) {
            el.attachEvent("on" + eventName, eventFunc);
            return true;
        }

        return false;
    },

    // add script to dom
    require: function (url, args) {
        var me = this;
        args = args || {};

        var scriptTag = document.createElement('script');
        var headTag = document.getElementsByTagName('head')[0];
        if (!headTag) {
            return false;
        }

        setTimeout(function () {
            var f = (typeof args.success == 'function') ? args.success : function () {
            };
            args.failure = (typeof args.failure == 'function') ? args.failure : function () {
            };
            var fail = function () {
                if (!scriptTag.__es) {
                    scriptTag.__es = true;
                    scriptTag.id = 'failed';
                    args.failure(scriptTag);
                }
            };
            scriptTag.onload = function () {
                scriptTag.id = 'loaded';
                f(scriptTag);
            };
            scriptTag.type = 'text/javascript';
            scriptTag.async = (typeof args.async == 'boolean') ? args.async : false;
            scriptTag.charset = 'utf-8';
            me.__es = false;
            me.addEvent(scriptTag, 'error', fail); // when supported
            // when error event is not supported fall back to timer
            me.timer(15, 1000, 0, function () {
                return (scriptTag.id == 'loaded');
            }, function () {
                if (scriptTag.id != 'loaded') {
                    fail();
                }
            });
            scriptTag.src = url;
            setTimeout(function () {
                try {
                    headTag.appendChild(scriptTag);
                } catch (e) {
                    fail();
                }
            }, 1);
        }, (typeof args.delay == 'number') ? args.delay : 1);
        return true;
    }
};

$(document).ready(function () {
    var loader = new ScriptLoader();
    loader.require('resources/templates.js', {
        async: true, success: function () {
            alert('loaded');
        }, failure: function () {
            alert('NOT loaded');
        }
    });
});

4
Me vi obligado a usar $ .getScript de jQuery , ya que esta función falló para los scripts almacenados en caché en MSIE8-, desafortunadamente
Zathrus Writer

@ZathrusWriter probablemente sea una mejor idea, ¡gracias por hacérnoslo saber! Probablemente podría agregar un int aleatorio a la URL en este código y eliminaría el almacenamiento en caché.
Aram Kocharyan

2
Sí, Aram, eso ciertamente funcionaría, sin embargo, también invalidaría el almacenamiento en caché del navegador, por lo que la sobrecarga en tal caso probablemente no valga la pena;)
Escritor Zathrus

@ZathrusWriter, entonces, ¿cómo funciona el funcionamiento de la implementación de jQuery?
Pacerier

@Pacerier lo siento, no soy un desarrollador principal de jQuery, así que realmente no puedo responder eso
Zathrus Writer

18

mi solución de trabajo limpia (2017)

function loaderScript(scriptUrl){
   return new Promise(function (res, rej) {
    let script = document.createElement('script');
    script.src = scriptUrl;
    script.type = 'text/javascript';
    script.onError = rej;
    script.async = true;
    script.onload = res;
    script.addEventListener('error',rej);
    script.addEventListener('load',res);
    document.head.appendChild(script);
 })

}

Como señaló Martin, usado así:

const event = loaderScript("myscript.js")
  .then(() => { console.log("loaded"); })
  .catch(() => { console.log("error"); });

O

try{
 await loaderScript("myscript.js")
 console.log("loaded"); 
}catch{
 console.log("error");
}

1
Úselo de la siguiente manera:loaderScript("myscript.js").then(() => { console.log("loaded"); }).catch(() => { console.log("error"); });
Martin Wantke

17

Sé que este es un hilo antiguo, pero tengo una buena solución para ti (creo). Está copiado de una clase mía, que maneja todas las cosas de AJAX.

Cuando el script no se puede cargar, establece un controlador de errores, pero cuando el controlador de errores no es compatible, recurre a un temporizador que busca errores durante 15 segundos.

function jsLoader()
{
    var o = this;

    // simple unstopable repeat timer, when t=-1 means endless, when function f() returns true it can be stopped
    o.timer = function(t, i, d, f, fend, b)
    {
        if( t == -1 || t > 0 )
        {
            setTimeout(function() {
                b=(f()) ? 1 : 0;
                o.timer((b) ? 0 : (t>0) ? --t : t, i+((d) ? d : 0), d, f, fend,b );
            }, (b || i < 0) ? 0.1 : i);
        }
        else if(typeof fend == 'function')
        {
            setTimeout(fend, 1);
        }
    };

    o.addEvent = function(el, eventName, eventFunc)
    {
        if(typeof el != 'object')
        {
            return false;
        }

        if(el.addEventListener)
        {
            el.addEventListener (eventName, eventFunc, false);
            return true;
        }

        if(el.attachEvent)
        {
            el.attachEvent("on" + eventName, eventFunc);
            return true;
        }

        return false;
    };

    // add script to dom
    o.require = function(s, delay, baSync, fCallback, fErr)
    {
        var oo = document.createElement('script'),
        oHead = document.getElementsByTagName('head')[0];
        if(!oHead)
        {
            return false;
        }

        setTimeout( function() {
            var f = (typeof fCallback == 'function') ? fCallback : function(){};
            fErr = (typeof fErr == 'function') ? fErr : function(){
                alert('require: Cannot load resource -'+s);
            },
            fe = function(){
                if(!oo.__es)
                {
                    oo.__es = true;
                    oo.id = 'failed';
                    fErr(oo);
                }
            };
            oo.onload = function() {
                oo.id = 'loaded';
                f(oo);
            };
            oo.type = 'text/javascript';
            oo.async = (typeof baSync == 'boolean') ? baSync : false;
            oo.charset = 'utf-8';
            o.__es = false;
            o.addEvent( oo, 'error', fe ); // when supported

            // when error event is not supported fall back to timer
            o.timer(15, 1000, 0, function() {
                return (oo.id == 'loaded');
            }, function(){ 
                if(oo.id != 'loaded'){
                    fe();
                }
            });
            oo.src = s;
            setTimeout(function() {
                try{
                    oHead.appendChild(oo);
                }catch(e){
                    fe();
                }
            },1); 
        }, (typeof delay == 'number') ? delay : 1);  
        return true;
    };

}

$(document).ready( function()
{
    var ol = new jsLoader();
    ol.require('myscript.js', 800, true, function(){
        alert('loaded');
    }, function() {
        alert('NOT loaded');
    });
});

4
... ¿de dónde vino jQuery?
Naftali alias Neal

1
Y también, es una solución para
varios

1
@Erwinus No verifiqué los encabezados, fue solo una verificación rápida entre navegadores que realicé y $ .getScript siempre se ejecutó sin problemas, así que me quedé con él ... puedes probarlo tú mismo, estoy usando W7 y XAMPP aquí
Zathrus Writer

19
Si esto funciona o no, es muy doloroso leerlo, y mucho menos depurarlo. Ese es un formato bastante pobre y un estilo de codificación realmente atroz. La denominación de variables por sí sola es un desastre.
Thor84no

7
Si no ve el valor del código legible (y podría hacerlo legible sin ningún cambio en el código realmente ejecutado), entonces lo siento por cada persona que tiene que trabajar con usted y su código.
Thor84no

10

Para verificar si el javascript nonexistant.jsno devolvió ningún error, debe agregar una variable dentro de http://fail.org/nonexistant.jslike var isExecuted = true;y luego verificar si existe cuando se carga la etiqueta del script.

Sin embargo, si solo desea verificar que se nonexistant.jsdevolvió sin un 404 (lo que significa que existe), puede probar con una isLoadedvariable ...

var isExecuted = false;
var isLoaded = false;
script_tag.onload = script_tag.onreadystatechange = function() {
    if(!this.readyState ||
        this.readyState == "loaded" || this.readyState == "complete") {
        // script successfully loaded
        isLoaded = true;

        if(isExecuted) // no error
    }
}

Esto cubrirá ambos casos.


1
Funciona, pero en realidad no hace lo que quiero; una falla en ese caso nunca desencadenaría un evento. No quiero tener que sondear una variable y, si sigue siendo falsa después de unos segundos, activar la devolución de llamada en caso de falla.
David

¿Qué tipo de error está intentando recuperar? ¿No se carga? ¿No se pudo ejecutar javascript en nonexstant.js? ¿Error de respuesta HTTP? Sea más descriptivo.
Luca Matteis

Cualquiera de los anteriores sería bueno. Sin embargo, me preocupo específicamente por un error 404.
David

404, lo que significa que desea verificar si el archivo nonexistant.js no existe. ¿Pero si quiere comprobar si no devolvió ningún error?
Luca Matteis

Hola David, deberías poder asumir que si this.readyState / ... no es verdadero, entonces el script no se pudo cargar. Básicamente un onError.
Cody

7

Espero que esto no sea rechazado, porque en circunstancias especiales es la forma más confiable de resolver el problema. En cualquier momento que el servidor le permita obtener un recurso de Javascript usando CORS ( http://en.wikipedia.org/wiki/Cross-origin_resource_sharing ), tiene una amplia gama de opciones para hacerlo.

El uso de XMLHttpRequest para recuperar recursos funcionará en todos los navegadores modernos, incluido IE. Ya que está buscando cargar Javascript, tiene Javascript disponible para usted en primer lugar. Puede realizar un seguimiento del progreso mediante readyState ( http://en.wikipedia.org/wiki/XMLHttpRequest#The_onreadystatechange_event_listener ). Finalmente, una vez que reciba el contenido del archivo, puede ejecutarlo con eval (). Sí, dije eval, porque en términos de seguridad no es diferente de cargar el script normalmente. De hecho, John Resig sugiere una técnica similar para tener etiquetas más agradables ( http://ejohn.org/blog/degrading-script-tags/ ).

Este método también le permite separar la carga de la evaluación y ejecutar funciones antes y después de que ocurra la evaluación. Se vuelve muy útil cuando se cargan scripts en paralelo, pero se evalúan uno tras otro, algo que los navegadores pueden hacer fácilmente cuando coloca las etiquetas en HTML, pero no le permiten agregar scripts en tiempo de ejecución con Javascript.

CORS también es preferible a JSONP para cargar scripts ( http://en.wikipedia.org/wiki/XMLHttpRequest#Cross-domain_requests ). Sin embargo, si está desarrollando sus propios widgets de terceros para incrustarlos en otros sitios, debería cargar los archivos Javascript de su propio dominio en su propio iframe (nuevamente, usando AJAX)

En breve:

  1. Intente ver si puede cargar el recurso usando AJAX GET

  2. Utilice eval después de que se haya cargado correctamente

Para mejorarlo:

  1. Consulte los encabezados de control de caché que se envían

  2. Busque almacenar en caché el contenido en localStorage, si es necesario

  3. Consulte el "javascript degradante" de Resig para obtener un código más limpio

  4. Echa un vistazo a require.js


NB que de esta manera requiere que el servidor de origen tenga CORS habilitado, lo cual no siempre es así o controlable: |
rogerdpack

5

Este truco me funcionó, aunque admito que probablemente esta no sea la mejor manera de resolver este problema. En lugar de intentar esto, debería ver por qué no se cargan los javascripts. Intente mantener una copia local del script en su servidor, etc. o consulte con el proveedor externo desde donde está intentando descargar el script.

De todos modos, aquí está la solución: 1) Inicialice una variable en falso 2) Configúrelo en verdadero cuando se cargue el javascript (usando el atributo onload) 3) verifique si la variable es verdadera o falsa una vez que se haya cargado el cuerpo HTML

<html>
  <head>
    <script>
      var scriptLoaded = false;

      function checkScriptLoaded() {
        if (scriptLoaded) {
          // do something here
        } else {
          // do something else here!
        }
      }
    </script>
    <script src="http://some-external-script.js" onload="scriptLoaded=true;" />
  </head>
  <body onload="checkScriptLoaded()">
    <p>My Test Page!</p>
  </body>
</html>

1
¿Qué pasa si el script todavía se está cargando? ¿Cómo saber si no se encontró el archivo o si solo tiene que esperar?
Osa

Esta solución funciona en mis pruebas, siempre que la etiqueta del script se coloque directamente en la fuente del documento. El evento de carga del documento no se activa hasta que todos los recursos a los que se hace referencia en el origen de la página ya se hayan cargado (o hayan fallado). Sin embargo, si necesita insertar scripts en el DOM más adelante, necesita otro enfoque.
Jamey Sharp

Gran solucion No entiendo por qué no se ha votado a favor.
Lotfi

Esto supone que el script se cargará sincrónicamente bloqueando todo lo demás, lo que no siempre es cierto. De hecho, no es una forma recomendada de cargar scripts.
Vitim.us

4

Aquí hay otra solución basada en JQuery sin temporizadores:

<script type="text/javascript">
function loadScript(url, onsuccess, onerror) {
$.get(url)
    .done(function() {
        // File/url exists
        console.log("JS Loader: file exists, executing $.getScript "+url)
        $.getScript(url, function() {
            if (onsuccess) {
                console.log("JS Loader: Ok, loaded. Calling onsuccess() for " + url);
                onsuccess();
                console.log("JS Loader: done with onsuccess() for " + url);
            } else {
                console.log("JS Loader: Ok, loaded, no onsuccess() callback " + url)
            }
        });
    }).fail(function() {
            // File/url does not exist
            if (onerror) {
                console.error("JS Loader: probably 404 not found. Not calling $.getScript. Calling onerror() for " + url);
                onerror();
                console.error("JS Loader: done with onerror() for " + url);
            } else {
                console.error("JS Loader: probably 404 not found. Not calling $.getScript. No onerror() callback " + url);
            }
    });
}
</script>

Gracias a: https://stackoverflow.com/a/14691735/1243926

Uso de muestra (muestra original de la documentación de JQuery getScript ):

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>jQuery.getScript demo</title>
  <style>
  .block {
     background-color: blue;
     width: 150px;
     height: 70px;
     margin: 10px;
  }
  </style>
  <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>

<button id="go">&raquo; Run</button>
<div class="block"></div>

<script>


function loadScript(url, onsuccess, onerror) {
$.get(url)
    .done(function() {
        // File/url exists
        console.log("JS Loader: file exists, executing $.getScript "+url)
        $.getScript(url, function() {
            if (onsuccess) {
                console.log("JS Loader: Ok, loaded. Calling onsuccess() for " + url);
                onsuccess();
                console.log("JS Loader: done with onsuccess() for " + url);
            } else {
                console.log("JS Loader: Ok, loaded, no onsuccess() callback " + url)
            }
        });
    }).fail(function() {
            // File/url does not exist
            if (onerror) {
                console.error("JS Loader: probably 404 not found. Not calling $.getScript. Calling onerror() for " + url);
                onerror();
                console.error("JS Loader: done with onerror() for " + url);
            } else {
                console.error("JS Loader: probably 404 not found. Not calling $.getScript. No onerror() callback " + url);
            }
    });
}


loadScript("https://raw.github.com/jquery/jquery-color/master/jquery.color.js", function() {
  console.log("loaded jquery-color");
  $( "#go" ).click(function() {
    $( ".block" )
      .animate({
        backgroundColor: "rgb(255, 180, 180)"
      }, 1000 )
      .delay( 500 )
      .animate({
        backgroundColor: "olive"
      }, 1000 )
      .delay( 500 )
      .animate({
        backgroundColor: "#00f"
      }, 1000 );
  });
}, function() { console.error("Cannot load jquery-color"); });


</script>
</body>
</html>

¡Buen Sergey! Entonces, ¿está usando .get () para verificar si el archivo existe y .getScript () para verificar si se puede ejecutar / cargar sin errores?
jjwdesign

2
Si. Según recuerdo, este enfoque tiene limitaciones: no podrá cargar muchas secuencias de comandos de esta manera, si no recuerdo mal, debido a las restricciones de secuencias de comandos entre dominios.
Osa

El problema con el uso de jQuery (u otra biblioteca) es que primero debe cargar esa biblioteca. Entonces, ¿cómo verifica si esa biblioteca no se cargó?
Pacerier

También he adoptado este enfoque, pero recomiendo usarlo cache:truepara la llamada $ .getScript (está desactivado de forma predeterminada). De esta manera, para la mayoría de las solicitudes, utiliza automáticamente la versión en caché para la llamada getScript (ahorrándole latencia)
Laurens Rietveld

2

Esto se puede hacer de forma segura utilizando promesas.

function loadScript(src) {
  return new Promise(function(resolve, reject) {
    let script = document.createElement('script');
    script.src = src;

    script.onload = () => resolve(script);
    script.onerror = () => reject(new Error("Script load error: " + src));

    document.head.append(script);
  });
}

y usa así

let promise = loadScript("https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js");

promise.then(
  script => alert(`${script.src} is loaded!`),
  error => alert(`Error: ${error.message}`)
);

1

La razón por la que no funciona en Safari es porque está utilizando la sintaxis de atributos. Sin embargo, esto funcionará bien:

script_tag.addEventListener('error', function(){/*...*/}, true);

... excepto en IE.

Si desea verificar la secuencia de comandos ejecutada con éxito, simplemente configure una variable usando esa secuencia de comandos y verifique que esté configurada en el código externo.


Eso en realidad no hace ninguna diferencia para Safari, todavía no activa el controlador de errores.
David

Tuve un problema con un controlador onclick en safari y esto fue lo que lo solucionó, así que pensé que también sería lo mismo para un error. Aparentemente no ...

1
¿Debería funcionar esto también para las etiquetas de script incluidas estáticamente o solo para las que se inyectan dinámicamente? Intenté usarlo para detectar si jQuery no se pudo cargar pero no funcionó. No estoy seguro de si lo estoy haciendo mal o simplemente no funciona en este caso.
hippietrail

1
@hippietrail: un detector de eventos nunca funcionará en un HTML estático <script>. Si intenta agregarlo antes, obtendrá un error de que la etiqueta no existe, y si lo agrega después, el script ya se ejecutó y activó sus eventos. La única forma es buscar los efectos secundarios causados ​​por el guión.

Gracias flussence. Lástima que esto solo funcione para 404, no para errores JS. Establecer una variable dentro del script no siempre es factible.
Jo Liss

0

Se propuso establecer un tiempo de espera y luego asumir una falla de carga después de un tiempo de espera.

setTimeout(fireCustomOnerror, 4000);

El problema con ese enfoque es que la suposición se basa en el azar. Una vez que expira el tiempo de espera, la solicitud sigue pendiente. Es posible que se cargue la solicitud del script pendiente, incluso después de que el programador haya asumido que no se cargará.

Si la solicitud se puede cancelar, entonces el programa podría esperar un período y luego cancelar la solicitud.


0

Así es como utilicé una promesa para detectar errores de carga que se emiten en el objeto de la ventana:

<script type='module'>
window.addEventListener('error', function(error) {
  let url = error.filename
  url = url.substring(0, (url.indexOf("#") == -1) ? url.length : url.indexOf("#"));
  url = url.substring(0, (url.indexOf("?") == -1) ? url.length : url.indexOf("?"));
  url = url.substring(url.lastIndexOf("/") + 1, url.length);
  window.scriptLoadReject && window.scriptLoadReject[url] && window.scriptLoadReject[url](error);
}, true);
window.boot=function boot() {
  const t=document.createElement('script');
  t.id='index.mjs';
  t.type='module';
  new Promise((resolve, reject) => {
    window.scriptLoadReject = window.scriptLoadReject || {};
    window.scriptLoadReject[t.id] = reject;
    t.addEventListener('error', reject);
    t.addEventListener('load', resolve); // Careful load is sometimes called even if errors prevent your script from running! This promise is only meant to catch errors while loading the file.
  }).catch((value) => {
    document.body.innerHTML='Error loading ' + t.id + '! Please reload this webpage.<br/>If this error persists, please try again later.<div><br/>' + t.id + ':' + value.lineno + ':' + value.colno + '<br/>' + (value && value.message);
  });
  t.src='./index.mjs'+'?'+new Date().getTime();
  document.head.appendChild(t);
};
</script>
<script nomodule>document.body.innerHTML='This website needs ES6 Modules!<br/>Please enable ES6 Modules and then reload this webpage.';</script>
</head>

<body onload="boot()" style="margin: 0;border: 0;padding: 0;text-align: center;">
  <noscript>This website needs JavaScript!<br/>Please enable JavaScript and then reload this webpage.</noscript>

0

Bueno, la única forma en que puedo pensar en hacer todo lo que quieres es bastante fea. Primero realice una llamada AJAX para recuperar el contenido del archivo Javascript. Cuando esto se complete, puede verificar el código de estado para decidir si fue exitoso o no. Luego tome el responseText del objeto xhr y envuélvalo en un try / catch, cree dinámicamente una etiqueta de secuencia de comandos, y para IE puede establecer la propiedad de texto de la etiqueta de secuencia de comandos en el texto JS, en todos los demás navegadores debería poder agregue un nodo de texto con el contenido a la etiqueta del script. Si hay algún código que espera que una etiqueta de secuencia de comandos contenga realmente la ubicación src del archivo, esto no funcionará, pero debería estar bien para la mayoría de las situaciones.


Esta solución está obsoleta con los navegadores modernos.
Simon_Weaver

0

evento de error

* Actualización de agosto de 2017: Chrome y Firefox activan un error. onload es disparado por Internet Explorer. Edge no dispara ni sobre error ni sobrecarga. No usaría este método, pero podría funcionar en algunos casos. Ver también

<link> onerror no funciona en IE

*

Definición y uso El evento onerror se activa si ocurre un error al cargar un archivo externo (por ejemplo, un documento o una imagen).

Consejo: cuando se usa en medios de audio / video, los eventos relacionados que ocurren cuando hay algún tipo de alteración en el proceso de carga de medios son:

  • onabort
  • uno vacio
  • instalado
  • suspender

En HTML:

elemento onerror = "myScript">

En JavaScript , usando el método addEventListener ():

object.addEventListener ("error", myScript);

Nota: El método addEventListener () no es compatible con Internet Explorer 8 y versiones anteriores.

Ejemplo Ejecute un JavaScript si ocurre un error al cargar una imagen:

img src = "image.gif" onerror = "myFunction ()">

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.