Ich habe mein JavaScript in verschiedene Dateien aufgeteilt. Ich möchte verhindern, dass JavaScript-Dateien zweimal geladen werden. Wie kann ich das machen?
Antworten
Zu viele Anzeigen?Hier ist ein Test, um zu sehen, ob ein Skript aufgrund des Pfads zur js-Datei eingeschlossen wurde:
function isScriptAlreadyIncluded(src){
var scripts = document.getElementsByTagName("script");
for(var i = 0; i < scripts.length; i++)
if(scripts[i].getAttribute('src') == src) return true;
return false;
}
Es funktioniert für alle Skripte, die nicht über AJAX geladen wurden, obwohl Sie es möglicherweise ändern möchten, wenn Sie JSONP-Code ausführen.
Manchmal wurde die js-Datei auf andere Weise geladen (zum Beispiel über js).
Dann kann window.performance
nützlich sein. Anstatt wie in anderen Antworten unter den script
-Tags zu überprüfen, können wir unter den geladenen Ressourcen prüfen mit:
let resources = performance.getEntries()
.filter(e => e.entryType === 'resource')
.map(e => e.name);
if (resources.indexOf("//domain.com/path/to/script.js") === -1) {
// Skript wurde noch nicht geladen.
}
Die Browser-Kompatibilität von window.performance
ist heutzutage nicht schlecht: https://caniuse.com/mdn-api_performance_getentries
Wenn wir sowohl die script
-Tags überprüfen möchten (für alle Skript-Tags im DOM bis zu diesem Zeitpunkt, einschließlich URLs von Skripts, die möglicherweise noch nicht geladen wurden) als auch die window.resources
(für alle bis zu diesem Zeitpunkt geladenen Skripte, einschließlich der über js geladenen), könnten wir es in einer Funktion zusammenfassen:
function is_script_already_included(src){
const found_in_resources = performance.getEntries()
.filter(e => e.entryType === 'resource')
.map(e => e.name)
.indexOf(src) !== -1;
const found_in_script_tags = document.querySelectorAll(`script[src*="${src}"]`).length > 0;
return found_in_resources || found_in_script_tags;
}
Include sie nicht zweimal. Immerhin bist du es, der die Includes macht.
Wenn du diese Inklusionen jedoch dynamisch machst, kannst du überprüfen, ob eine globale Funktion oder ein Objekt vom Skript gesetzt wurde. Wenn zum Beispiel das folgende Skript in einer Datei steht:
Foo = function () {};
Und dann füge es so ein:
Vor dem Parsen des Skript-Tags durch den Browser ist Foo
undefined
. Nachdem der Tag verarbeitet wurde, ist Foo
eine Function
. Du könntest auf dieser Logik basierend feststellen, ob du eine Datei einbeziehen solltest oder nicht.
Ich habe das mit einer generischen selbstaufrufenden Funktion gelöst, die am Ende jedes dynamisch geladenen Skripts hinzugefügt wird.
Zuerst - durch Deklarieren eines neuen leeren Arrays in meiner Basdatei oder einem Skript, das immer geladen wird, z. B. der Hauptseite in meinem Fall index.php
var scriptsLoaded = new Array();
Fügen Sie dann eine selbstausführende Funktion am Ende des geladenen Skripts hinzu:
(function () { scriptsLoaded.push( 'this_script_name.js' ) })();
Mit diesem Ansatz sollte sich jede Datei im scriptsLoaded-Array nur auf Skripts beziehen, die bereits vollständig geladen wurden. Einfaches Überprüfen dieses Arrays würde anzeigen, ob ein Skript geladen wurde, was auch als Prüfung verwendet werden kann, ob Onload-Style-Funktionen für das benötigte Skript ausgeführt werden sollen
Ohne die Verwendung eines Frameworks (das ich kenne), kann dies nur erreicht werden, indem überprüft wird, ob eine bestimmte Variable im globalen Bereich bereits deklariert wurde.
Sie könnten eine Variable var include1 = true;
innerhalb von include1.js
deklarieren und etwas ähnliches tun wie
if (window.include1 !== true) {
// Datei dynamisch laden
}
- See previous answers
- Weitere Antworten anzeigen