Überprüfen Sie, ob das externe Skript geladen ist

79

Ich erstelle ein JQuery-Plugin und möchte überprüfen, ob ein externes Skript geladen ist. Dies ist für eine interne Web-App und ich kann den Skriptnamen / -speicherort konsistent halten (mysscript.js). Dies ist auch ein Ajaxy-Plugin, das auf der Seite mehrmals aufgerufen werden kann.

Wenn ich überprüfen kann, ob das Skript nicht geladen ist, lade ich es mit:

jQuery.getScript()

Wie kann ich überprüfen, ob das Skript geladen ist, weil ich nicht möchte, dass dasselbe Skript mehr als einmal auf die Seite geladen wird? Ist dies etwas, worüber ich mir aufgrund des Zwischenspeicherns des Skripts keine Sorgen machen sollte?

Update: Ich habe möglicherweise keine Kontrolle darüber, wer dieses Plugin in unserer Organisation verwendet, und kann möglicherweise nicht erzwingen, dass sich das Skript nicht bereits auf der Seite mit oder ohne eine bestimmte ID befindet, aber der Skriptname befindet sich immer an derselben Stelle wie der selbe Name. Ich hoffe, ich kann den Namen des Skripts verwenden, um zu überprüfen, ob es tatsächlich geladen ist.

AGoodDisplayName
quelle
Dieser Thread befindet sich oben in den häufig gestellten Fragen zu SO-Abfrage-Tags und bietet eine Vielzahl von Methoden, mit denen überprüft werden kann, ob das Skript stackoverflow.com/questions/1014203/… vorhanden ist. Viele Rückmeldungen zu verschiedenen Methoden
charlietfl

Antworten:

139

Wenn das Skript Variablen oder Funktionen im globalen Bereich erstellt, können Sie deren Existenz überprüfen:

Externes JS (im globalen Bereich) -

var myCustomFlag = true;

Und um zu überprüfen, ob dies ausgeführt wurde:

if (typeof window.myCustomFlag == 'undefined') {
    //the flag was not found, so the code has not run
    $.getScript('<external JS>');
}

Aktualisieren

Sie können die Existenz des <script>betreffenden Tags überprüfen , indem Sie alle <script>Elemente auswählen und ihre srcAttribute überprüfen :

//get the number of `<script>` elements that have the correct `src` attribute
var len = $('script').filter(function () {
    return ($(this).attr('src') == '<external JS>');
}).length;

//if there are no scripts that match, the load it
if (len === 0) {
    $.getScript('<external JS>');
}

Oder Sie backen diese .filter()Funktionalität einfach direkt in den Selektor:

var len = $('script[src="<external JS>"]').length;
Jaspis
quelle
Dies war eine gute Antwort. Leider fügt die Methode jquery.getScript das Skript ohne Angabe einer Quelle hinzu. Also konnte ich es nicht finden. Ich habe einen Teil Ihrer Antwort verwendet, um dies zu lösen, also +1.
AGoodDisplayName
@AGoodDisplayName Im Rückruf für können $.getScript()Sie ein globales Flag setzen, das überprüft werden kann : $.getScript('<external JS>, function () { window.myCustomFlag = true; }'). Dann können Sie einfach prüfen, ob das spezifische <script>Element oder die myCustomFlagVariable vorhanden ist.
Jasper
@ Jasper, ja, das ist wahrscheinlich der effizienteste Weg, weshalb ich Ihre Antwort akzeptiere. Ich habe gerade meine Lösung eingefügt (in die ich eine globale Flagge einfügen sollte).
AGoodDisplayName
21
Die Überprüfung der Skript-src ist in Ordnung, aber das Problem ist, dass das Vorhandensein eines Skript-Tags mit der richtigen src nicht bedeutet, dass genau das Skript geladen ist. Das Einfügen eines Tags ist nur der Beginn der Ladephase.
Karol
3
@Jasper von einer Frage Ich nahm an, dass Skripte dynamisch geladen werden, indem das Tag in DOM eingefügt wird. Dies ist der einzige Fall, in dem dasselbe Skript mehrmals eingefügt werden kann (niemand fügt das Skript in HTML ein und versucht dann, es erneut dynamisch zu laden). Sobald Sie ein Skript-Tag eingefügt haben, warten Sie immer noch, bis es geladen ist. In diesem Fall funktioniert Ihre Antwort nicht, da nur geprüft wird, ob ein Skript-Tag vorhanden ist oder nicht.
Karol
18

Die Antwort von @ jasper ist völlig richtig, aber mit modernen Browsern könnte eine Standard-Javascript-Lösung sein:

function isScriptLoaded(src)
{
    return document.querySelector('script[src="' + src + '"]') ? true : false;
}
Abhishek
quelle
2
Sie können Booleananstelle des bedingten Operators verwenden, wenn Sie möchten
CertainPerformance
Es kann einfach seinreturn document.querySelector('script[src="' + src + '"]');
Harshal Parekh
10

Das war jetzt, da ich weiß, wie es geht, sehr einfach, dank all der Antworten, die mich zur Lösung geführt haben. Ich musste $ .getScript () aufgeben, um die Quelle des Skripts anzugeben ... manchmal ist es am besten, Dinge manuell zu erledigen.

Lösung

//great suggestion @Jasper
var len = $('script[src*="Javascript/MyScript.js"]').length; 

if (len === 0) {
        alert('script not loaded');

        loadScript('Javascript/MyScript.js');

        if ($('script[src*="Javascript/MyScript.js"]').length === 0) {
            alert('still not loaded');
        }
        else {
            alert('loaded now');
        }
    }
    else {
        alert('script loaded');
    }


function loadScript(scriptLocationAndName) {
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = scriptLocationAndName;
    head.appendChild(script);
}
AGoodDisplayName
quelle
8

Einige zu viele Antworten auf diese Frage, aber ich denke, es lohnt sich, diese Lösung hinzuzufügen. Es kombiniert einige verschiedene Antworten.

Wichtige Punkte für mich waren

  • Fügen Sie ein # id-Tag hinzu, damit es leicht zu finden und nicht zu duplizieren ist
  • Verwenden Sie .onload (), um zu warten, bis das Skript vollständig geladen ist, bevor Sie es verwenden

    mounted() {
      // First check if the script already exists on the dom
      // by searching for an id
      let id = 'googleMaps'
      if(document.getElementById(id) === null) {
        let script = document.createElement('script')
        script.setAttribute('src', 'https://maps.googleapis.com/maps/api/js?key=' + apiKey)
        script.setAttribute('id', id)
        document.body.appendChild(script) 
    
        // now wait for it to load...
        script.onload = () => {
            // script has loaded, you can now use it safely
            alert('thank me later')
            // ... do something with the newly loaded script
        }      
      }
    }
    
comfytoday
quelle
6

Erstellen Sie das Skript-Tag mit einer bestimmten ID und prüfen Sie dann, ob diese ID vorhanden ist.

Alternativ können Sie die Skript-Tags durchlaufen, um nach dem Skript 'src' zu suchen, und sicherstellen, dass diese nicht bereits mit demselben Wert geladen sind wie der, den Sie vermeiden möchten.

Bearbeiten: folgende Rückmeldung, dass ein Codebeispiel nützlich wäre:

(function(){
    var desiredSource = 'https://sitename.com/js/script.js';
    var scripts       = document.getElementsByTagName('script');
    var alreadyLoaded = false;

    if(scripts.length){
        for(var scriptIndex in scripts) {
            if(!alreadyLoaded && desiredSource === scripts[scriptIndex].src) {
                alreadyLoaded = true;
            }
        }
    }
    if(!alreadyLoaded){
        // Run your code in this block?
    }
})();

Wie in den Kommentaren erwähnt ( https://stackoverflow.com/users/1358777/alwin-kesler ), kann dies eine Alternative sein (kein Benchmarking):

(function(){
    var desiredSource = 'https://sitename.com/js/script.js';
    var scripts = document.getElementsByTagName('script');
    var alreadyLoaded = false;

    for(var scriptIndex in document.scripts) {
        if(!alreadyLoaded && desiredSource === scripts[scriptIndex].src) {
            alreadyLoaded = true;
        }
    }
    if(!alreadyLoaded){
        // Run your code in this block?
    }
})();
MyStream
quelle
Dies ist die perfekte Lösung. Ich empfehle den zweiten.
Ilyas Karim
Es wäre großartig, wenn Sie Code mit diesen Ideen setzen könnten.
Ilyas Karim
document.scripts scheint schneller zu sein document.getElementsByTagName('script'), hat es aber nicht getestet
Alwin Kesler
1
@AlwinKesler, stimmte zu. Der Code wurde mit einer Alternative aktualisiert. Wäre gut, einen Benchmark zu bekommen.
MyStream
3

Eine andere Möglichkeit, um zu überprüfen, ob ein externes Skript geladen ist oder nicht, besteht darin, die Datenfunktion von jquery zu verwenden und ein Validierungsflag zu speichern. Beispiel als:

if(!$("body").data("google-map"))
    {
        console.log("no js");

        $.getScript("https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&callback=initilize",function(){
            $("body").data("google-map",true);

            },function(){
                alert("error while loading script");
            });
        }
    }
    else
    {
        console.log("js already loaded");
    }
Sunil Sharma
quelle
3

Zusammenführen mehrerer Antworten von oben zu einer benutzerfreundlichen Funktion

function GetScriptIfNotLoaded(scriptLocationAndName)
{
  var len = $('script[src*="' + scriptLocationAndName +'"]').length;

  //script already loaded!
  if (len > 0)
      return;

  var head = document.getElementsByTagName('head')[0];
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = scriptLocationAndName;
  head.appendChild(script);
}
Aaron Sherman
quelle
2

Ich denke, es ist besser, window.addEventListener ('error') zu verwenden, um den Skriptladefehler zu erfassen und erneut zu laden. Dies ist nützlich, wenn wir Skripte von einem CDN-Server laden. Wenn wir kein Skript vom CDN laden können, können wir es von unserem Server laden.

window.addEventListener('error', function(e) {
  if (e.target.nodeName === 'SCRIPT') {
    var scriptTag = document.createElement('script');
    scriptTag.src = e.target.src.replace('https://static.cdn.com/', '/our-server/static/');
    document.head.appendChild(scriptTag);
  }
}, true);
Herzog
quelle
1

Überprüfen Sie einfach , ob die globale Variable verfügbar ist , oder überprüfen Sie sie erneut . Um zu verhindern , dass der maximale Callstack überschritten wird, setzen Sie ein Timeout von 100 ms für die Prüfung:

function check_script_loaded(glob_var) {
    if(typeof(glob_var) !== 'undefined') {
    // do your thing
    } else {
    setTimeout(function() {
    check_script_loaded(glob_var)
    }, 100)
    }
}
Kybernetisch
quelle