Come sapere se un tag <script> non è stato caricato


112

Sto aggiungendo dinamicamente <script>tag a una pagina <head>e mi piacerebbe essere in grado di dire se il caricamento non è riuscito in qualche modo: un 404, un errore di script nello script caricato, qualunque sia.

In Firefox, funziona:

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);

Tuttavia, questo non funziona in IE o Safari.

Qualcuno conosce un modo per farlo funzionare in browser diversi da Firefox?

(Non credo che una soluzione che richiede l'inserimento di codice speciale all'interno dei file .js sia buona. È inelegante e inflessibile.)


4
Grande sito web, caricamento automatico delle dipendenze per i contenuti caricati tramite ajax. if+ il polling è un fastidioso cruft che non voglio dover inserire in tutti i JS.
David,

2
Potresti anche voler verificare la presenza di errori di caricamento quando si effettua una richiesta JSONP utilizzando l'iniezione di tag script ...
schellsan

Risposte:


36

Non sono presenti eventi di errore per il tag script. Puoi dire quando ha successo e presumere che non sia stato caricato dopo un timeout:

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

7
Il listener "onload" verrà attivato anche se è presente un errore javascript.
Luca Matteis

38
Ebbene, sì, se il file LOADS e c'è un errore nel file stesso, ma se il file non viene servito, l'onload non si attiverà mai.
Diodeus - James MacFarlane

1
sì, è vero, è per questo che ho chiesto di essere più specifico sul tipo di errore che sta cercando.
Luca Matteis

1
Ma il timeout deve essere fornito dal programmatore della pagina, giusto? Quindi il programmatore potrebbe scegliere un timeout diverso dal browser, presumere che il caricamento dello script sia scaduto e quindi farlo funzionare un po 'più tardi. O no?
Hippietrail

6
C'è un errore evnt per il tag script. Si attiverà quando la risorsa non viene trovata.
Nguyen Tran

24

Se ti interessano solo i browser html5 puoi usare l'evento di errore (poiché questo è solo per la gestione degli errori, dovrebbe essere ok solo per supportare questo sui browser di prossima generazione per KISS IMHO).

Dalle specifiche:

Se il valore dell'attributo src è una stringa vuota o se non è stato possibile risolverlo, l'agente utente deve mettere in coda un'attività per attivare un semplice evento denominato errore sull'elemento e interrompere questi passaggi.

~

Se il caricamento ha generato un errore (ad esempio un errore DNS o un errore HTTP 404) L'esecuzione del blocco di script deve consistere semplicemente nell'attivare un semplice evento denominato errore sull'elemento.

Ciò significa che non devi eseguire alcun polling soggetto a errori e puoi combinarlo con l'attributo async e defer per assicurarti che lo script non blocchi il rendering della pagina:

L'attributo defer può essere specificato anche se viene specificato l'attributo async, per fare in modo che i browser Web legacy che supportano solo defer (e non asincrono) tornino al comportamento defer invece del comportamento di blocco sincrono che è l'impostazione predefinita.

Altro su http://www.w3.org/TR/html5/scripting-1.html#script


1
Qualche idea di implementazioni JSONP, come quella in jQuery, supporta questo? Tutto ciò che ho letto qui sul rilevamento di errori di caricamento di JSONP dice che non può essere rilevato, ma un timeout può essere una soluzione alternativa e un timeout è stato aggiunto a una versione recente di JSONP. Sembra che questa risposta fornisca qualcosa di meglio del timeout, è corretto?
Hippietrail

1
esempio possibile per favore?
rogerdpack

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

@Rudey Uncaught SyntaxError: Unexpected token '<'(nell'ultimo Chrome)
daleyjem

@daleyjem sembra che tu abbia tentato di inserire un tag HTML in JavaScript. <script src="nonexistent.js" onerror="alert('error!')"></script>dovrebbe andare nel tuo file HTML, non in JS.
Rudey

21

La sceneggiatura di Erwinus funziona alla grande, ma non è codificata molto chiaramente. Mi sono preso la libertà di ripulirlo e decifrare cosa stava facendo. Ho apportato queste modifiche:

  • Nomi di variabili significativi
  • Uso di prototype.
  • require() utilizza una variabile argomento
  • Nessun alert()messaggio viene restituito per impostazione predefinita
  • Risolti alcuni errori di sintassi e problemi di ambito che stavo ottenendo

Grazie ancora a Erwinus, la funzionalità stessa è perfetta.

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
Sono stato costretto a utilizzare $ .getScript di jQuery , poiché questa funzione non è riuscita per gli script memorizzati nella cache in MSIE8-, sfortunatamente
Zathrus Writer

@ZathrusWriter è probabilmente un'idea migliore, grazie per avercelo fatto sapere! Probabilmente potresti aggiungere un int casuale all'URL in questo codice e rimuoverebbe la cache.
Aram Kocharyan

2
Sì Aram, questo farebbe sicuramente il trucco, tuttavia invaliderebbe anche il caching del browser, quindi l'overhead in questo caso probabilmente non ne vale davvero la pena;)
Zathrus Writer

@ZathrusWriter, quindi come funziona l'implementazione di jQuery?
Pacerier

@Pacerier mi dispiace, non sono uno sviluppatore core jQuery, quindi non posso davvero rispondere a questo
Zathrus Writer

18

la mia soluzione pulita di lavoro (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);
 })

}

Come ha sottolineato Martin, usato in questo modo:

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
Usalo come segue:loaderScript("myscript.js").then(() => { console.log("loaded"); }).catch(() => { console.log("error"); });
Martin Wantke,

17

So che questo è un vecchio thread ma ho una bella soluzione per te (credo). È copiato da una mia classe, che gestisce tutte le cose AJAX.

Quando lo script non può essere caricato, imposta un gestore degli errori, ma quando il gestore degli errori non è supportato, ricade su un timer che controlla gli errori per 15 secondi.

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
... da dove viene jQuery?
Naftali aka Neal

1
Inoltre, è una soluzione cross-browser ;-)
Codebeat

1
@Erwinus Non ho controllato le intestazioni, è stato solo un rapido controllo cross-browser che ho eseguito e $ .getScript ha sempre funzionato senza problemi, quindi mi sono bloccato ... puoi provare tu stesso, sto usando W7 e XAMPP qui
Zathrus Writer

19
Che funzioni o meno, è dannatamente doloroso da leggere, figuriamoci eseguire il debug. È una formattazione piuttosto scadente e uno stile di codifica davvero atroce. La sola denominazione delle variabili è un disastro.
Thor84no

7
Se non vedi il valore del codice leggibile (e potresti renderlo leggibile senza alcuna modifica al codice effettivamente eseguito), allora mi dispiace per ogni singola persona che deve lavorare con te e il tuo codice.
Thor84no

10

Per verificare se il javascript in nonexistant.jsnon ha restituito errori devi aggiungere una variabile all'interno di http://fail.org/nonexistant.jslike var isExecuted = true;e poi controllare se esiste quando viene caricato il tag script.

Tuttavia, se vuoi solo controllare che il nonexistant.jsrestituito senza un 404 (il che significa che esiste), puoi provare con una isLoadedvariabile ...

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
    }
}

Questo coprirà entrambi i casi.


1
Funziona, ma in realtà non fa quello che voglio: un fallimento in tal caso non attiverebbe mai un evento. Non voglio dover eseguire il polling per una variabile e, se è ancora falso dopo pochi secondi, attivare il callback in caso di errore.
David,

Che tipo di errore stai cercando di recuperare? Mancato caricamento? Mancata esecuzione del javascript in nonexstant.js? Errore di risposta HTTP? Si prega di essere più descrittivi.
Luca Matteis

Uno qualsiasi dei precedenti andrebbe bene. Tuttavia, mi interessa in particolare un errore 404.
David,

404, il che significa che vuoi controllare se il file nonexistant.js non esiste? Ma se vuoi controllare se non ha restituito errori?
Luca Matteis

Ehi David, dovresti essere in grado di presumere che se this.readyState / ... non è vero, lo script non è stato caricato. Fondamentalmente un onError.
Cody

7

Spero che questo non venga svalutato, perché in circostanze speciali è il modo più affidabile per risolvere il problema. Ogni volta che il server ti consente di ottenere una risorsa Javascript utilizzando CORS ( http://en.wikipedia.org/wiki/Cross-origin_resource_sharing ), hai una vasta gamma di opzioni per farlo.

L'utilizzo di XMLHttpRequest per recuperare le risorse funzionerà su tutti i browser moderni, incluso IE. Dato che stai cercando di caricare Javascript, hai Javascript a tua disposizione in primo luogo. Puoi tenere traccia dei progressi utilizzando readyState ( http://en.wikipedia.org/wiki/XMLHttpRequest#The_onreadystatechange_event_listener ). Infine, una volta ricevuto il contenuto del file, puoi eseguirlo con eval (). Sì, ho detto eval, perché dal punto di vista della sicurezza non è diverso dal caricare normalmente lo script. In effetti, una tecnica simile è suggerita da John Resig per avere tag più belli ( http://ejohn.org/blog/degrading-script-tags/ ).

Questo metodo consente inoltre di separare il caricamento da eval ed eseguire funzioni prima e dopo che si verifica l'eval. Diventa molto utile quando si caricano script in parallelo ma li si valuta uno dopo l'altro - cosa che i browser possono fare facilmente quando si inseriscono i tag in HTML, ma non te lo consentono aggiungendo script in fase di esecuzione con Javascript.

CORS è anche preferibile a JSONP per il caricamento degli script ( http://en.wikipedia.org/wiki/XMLHttpRequest#Cross-domain_requests ). Tuttavia, se stai sviluppando i tuoi widget di terze parti da incorporare in altri siti, dovresti effettivamente caricare i file Javascript dal tuo dominio nel tuo iframe (di nuovo, usando AJAX)

In breve:

  1. Prova a vedere se riesci a caricare la risorsa utilizzando AJAX GET

  2. Usa eval dopo che è stato caricato con successo

Per migliorarlo:

  1. Controlla le intestazioni di controllo della cache inviate

  2. Se necessario, cerca di memorizzare nella cache il contenuto in localStorage

  3. Dai un'occhiata al "javascript degradante" di Resig per un codice più pulito

  4. Dai un'occhiata a require.js


NB in ​​questo modo è necessario che il server di origine abbia CORS abilitato, il che non è sempre il caso o controllabile: |
rogerdpack

5

Questo trucco ha funzionato per me, anche se ammetto che questo probabilmente non è il modo migliore per risolvere questo problema. Invece di provare questo, dovresti vedere perché i javascript non vengono caricati. Prova a mantenere una copia locale dello script nel tuo server, ecc. O controlla con il fornitore di terze parti da cui stai tentando di scaricare lo script.

Ad ogni modo, ecco la soluzione alternativa: 1) Inizializza una variabile su false 2) Impostala su true quando viene caricato javascript (utilizzando l'attributo onload) 3) controlla se la variabile è true o false una volta caricato il corpo 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
E se lo script si sta ancora caricando? Come fai a sapere se il file non è stato trovato o se devi solo aspettare?
osa

Questa soluzione funziona nei miei test, a condizione che il tag dello script sia posizionato direttamente nell'origine del documento. L'evento onload del documento non si attiva finché tutte le risorse a cui si fa riferimento nell'origine della pagina non sono già state caricate (o non sono riuscite). Se hai bisogno di inserire script nel DOM in un secondo momento, però, hai bisogno di un altro approccio.
Jamey Sharp

Ottima soluzione. Non capisco perché non sia stato votato.
Lotfi

Ciò presuppone che lo script verrà caricato in modo sincrono bloccando tutto il resto, il che non è sempre vero. In effetti, non è un modo consigliato per caricare gli script.
Vitim.us

4

Ecco un'altra soluzione basata su JQuery senza timer:

<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>

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

Utilizzo di esempio (esempio originale dalla documentazione di 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>

Nice Sergey! Quindi, stai usando .get () per verificare se il file esiste e .getScript () per verificare se può essere eseguito / caricato senza errori?
jjwdesign

2
Sì. Per quanto ricordo, questo approccio ha dei limiti: non sarai in grado di caricare molti script in questo modo --- se ricordo bene, a causa delle restrizioni di scripting tra domini.
osa

Il problema con l'utilizzo di jQuery (o un'altra libreria) è che devi prima caricare quella libreria. Quindi come si controlla se quella libreria non è stata caricata?
Pacerier

Ho adottato anche questo approccio, ma consiglio di utilizzare cache:trueper la chiamata $ .getScript (questo è disattivato per impostazione predefinita). In questo modo, per la maggior parte delle richieste, utilizza automaticamente la versione cache per la chiamata getScript (risparmiando latenza)
Laurens Rietveld

2

Questo può essere fatto in sicurezza usando le promesse

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);
  });
}

e usa in questo modo

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

Il motivo per cui non funziona in Safari è perché stai utilizzando la sintassi degli attributi. Funzionerà bene però:

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

... tranne che in IE.

Se vuoi controllare lo script eseguito correttamente, imposta una variabile usando quello script e controlla che sia impostato nel codice esterno.


Questo in realtà non fa alcuna differenza per Safari: continua a non attivare il gestore degli errori.
David,

Ho avuto un problema con un gestore onclick in Safari e questo è stato ciò che lo ha risolto, quindi ho pensato che sarebbe stato lo stesso anche per onerror. Apparentemente no ...

1
Questo dovrebbe funzionare anche per i tag di script inclusi staticamente o solo per quelli iniettati dinamicamente? Ho appena provato a usarlo per rilevare se jQuery non è riuscito a caricare ma non ha funzionato. Non sono sicuro se sto sbagliando o semplicemente non funziona in questo caso.
Hippietrail

1
@hippietrail: un listener di eventi non funzionerà mai su un HTML statico <script>. Se provi ad aggiungerlo prima, ricevi un errore che il tag non esiste e se lo aggiungi dopo lo script è già stato eseguito e ha attivato i suoi eventi. L'unico modo è cercare gli effetti collaterali causati dallo script.

Grazie flussence. Peccato che funzioni solo per 404, non per errori JS. L'impostazione di una variabile all'interno dello script non è sempre praticabile.
Jo Liss

1

Evento onerror

* Aggiornamento agosto 2017: onerror viene lanciato da Chrome e Firefox. onload è attivato da Internet Explorer. Edge non genera né errore né caricamento. Non userei questo metodo, ma in alcuni casi potrebbe funzionare. Guarda anche

<link> onerror non funziona in IE

*

Definizione e utilizzo L'evento onerror viene attivato se si verifica un errore durante il caricamento di un file esterno (ad esempio un documento o un'immagine).

Suggerimento: se utilizzato su supporti audio / video, gli eventi correlati che si verificano quando si verifica un qualche tipo di disturbo al processo di caricamento del supporto sono:

  • OnAbort
  • onemptied
  • onstalled
  • onsuspend

In HTML:

elemento onerror = "myScript">

In JavaScript , utilizzando il metodo addEventListener ():

object.addEventListener ("errore", myScript);

Nota: il metodo addEventListener () non è supportato in Internet Explorer 8 e nelle versioni precedenti.

Esempio Esegui un JavaScript se si verifica un errore durante il caricamento di un'immagine:

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


0

È stato proposto di impostare un timeout e quindi presumere un errore di carico dopo un timeout.

setTimeout(fireCustomOnerror, 4000);

Il problema con questo approccio è che l'assunto è basato sul caso. Dopo la scadenza del timeout, la richiesta è ancora in sospeso. La richiesta per lo script in sospeso potrebbe caricarsi, anche dopo che il programmatore ha assunto che il caricamento non verrà eseguito.

Se la richiesta può essere annullata, il programma potrebbe attendere un periodo, quindi annullare la richiesta.


0

Ecco come ho utilizzato una promessa per rilevare gli errori di caricamento che vengono emessi sull'oggetto finestra:

<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

Bene, l'unico modo in cui posso pensare di fare tutto ciò che vuoi è piuttosto brutto. Prima esegui una chiamata AJAX per recuperare il contenuto del file Javascript. Al termine, puoi controllare il codice di stato per decidere se l'operazione è andata a buon fine o meno. Quindi prendi il responseText dall'oggetto xhr e racchiudilo in un try / catch, crea dinamicamente un tag script e per IE puoi impostare la proprietà text del tag script sul testo JS, in tutti gli altri browser dovresti essere in grado di aggiungere un nodo di testo con il contenuto al tag di script. Se c'è del codice che si aspetta che un tag script contenga effettivamente la posizione src del file, non funzionerà, ma dovrebbe andare bene per la maggior parte delle situazioni.


Questa soluzione è decisamente obsoleta con i browser moderni.
Simon_Weaver
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.