Gibt es eine Möglichkeit, eine Javascript-Datei genau wie ein synchrones XMLHttpRequest zu laden und auszuführen?
Ich verwende derzeit eine Synchronisierung XMLHttpRequest und dann Eval, aber das Debuggen dieses Codes ist sehr schwierig ...
Danke für Ihre Hilfe!
Update
Ich habe das jetzt ausprobiert:
test.html
<html>
<head>
<script type="text/javascript">
var s = document.createElement("script");
s.setAttribute("src","script.js");
document.head.appendChild(s);
console.log("done");
</script>
</head>
<body>
</body>
</html>
script.js
console.log("Hi");
Ausgabe: Fertig Hi
Es wurde also nicht synchron ausgeführt. Irgendeine Idee, "Hi" zuerst erscheinen zu lassen?
Update 2 Anderes Beispiel
test.html (Code innerhalb eines Skript-Tags)
var s = document.createElement("script");
s.setAttribute("src","script.js");
document.head.appendChild(s);
SayHi();
script.js
function SayHi(){
console.log("hi");
}
Ausgabe: Nicht gefundener ReferenceError: SayHi ist nicht definiert
Wenn Sie dies verwenden:
function loadScriptSync (src) {
var s = document.createElement('script');
s.src = src;
s.type = "text/javascript";
s.async = false; // <-- this is important
document.getElementsByTagName('head')[0].appendChild(s);
}
Sie können machen, was Sie wollen (obwohl in einer zusätzlichen Skriptdatei aufgeteilt)
test.html (Code innerhalb eines Skript-Tags):
loadScriptSync("script.js");
loadScriptSync("sayhi.js"); // you have to put the invocation into another script file
script.js :
function SayHi() {
console.log("hi");
}
sayhi.js :
SayHi();
Alle Skripts, die nach der Fertigstellung von DOM geladen werden, werden asynchron geladen. Der einzige Grund, warum der Browser sie synchron lädt, ist die Funktion write
, die etwas ausgeben kann. Sie können also Onload Callback des Skriptelements verwenden, um das zu erreichen, was Sie möchten.
var s = document.createElement("script");
s.setAttribute("src","script.js");
s.onload = function(){
console.log('Done');
}
document.head.appendChild(s);
Eine andere Möglichkeit besteht darin, die js-Datei über XHR zu laden und Code innerhalb des Skriptelements festzulegen:
window.onload = function(){
var req = new XMLHttpRequest();
req.open('GET', "test.js", false);
req.onreadystatechange = function(){
if (req.readyState == 4) {
var s = document.createElement("script");
s.appendChild(document.createTextNode(req.responseText));
document.head.appendChild(s);
}
};
req.send(null);
}
Aus einer ähnlichen Frage ( https://stackoverflow.com/a/3292763/235179 ):
<script type="text/javascript">
document.write('<script type="text/javascript" src="other.js"><\/script>');
</script>
<script type="text/javascript">
functionFromOther();
</script>
Entweder muss der vom document.write
'd-Skript aufgerufene Code in seinem eigenen <script>
oder in dem window.onload()
-Ereignis enthalten sein.
ihr Code, wenn zusammengesetzt, lautet:
1. create script element
2. set its attribute src
3. set its attribute deferred
4. display done...
dieser erste Teil stoppt die Ausführung und übergibt sie dem nächsten Skript
5. script executes and displays Hi
Alles ist sehr synchron ... In Javascript wird ein Teil des Codes vollständig ausgeführt, bis er in der letzten Zeile ausgeführt wird oder die Ausführung an interne Systeme (wie XHR oder Timer) übergeben wird.
Wenn Sie einige Teile für die spätere Ausführung vorbereiten möchten, bereiten Sie sie mit setTimeout
vor. Selbst wenn das Timeout kürzer ist als der Rest des Codes, dauert dies die Zeit, die es ausführt. Nachdem der Code ausgeführt wurde. Beispiel:
// some code
setTimeout(function(){ alert("I'm second alert"); }, 1);
longExecutionTask();
alert("I'm the first alert");
Auch wenn im obigen Code setTimeout
zur Ausführung nach 1 ms eingestellt ist, wird der Code erst gestartet, wenn der Code nach dessen Ausführung beendet ist, der mit der Anzeige einer alert
-Box endet. Dasselbe passiert in Ihrem Fall. Der erste Code-Stapel muss abgeschlossen sein, bevor etwas anderes gestartet werden kann.
Sie haben etwas mehr Code hinzugefügt, nachdem ich meine Antwort geschrieben habe. Hier finden Sie weitere Informationen.
Durch das Hinzufügen eines Skript-Tags wird es nicht sofort ausgeführt. Das Laden und Ausführen des Skripts geschieht, wenn der HTML-Parser zu dem von Ihnen hinzugefügten SCRIPT
-Element gelangt. Es wird es an diesem Punkt laden und seinen Inhalt auswerten/ausführen.
HEAD
wird analysiert und der untergeordnete Tag SCRIPT
wird analysiert und ausgeführt. Diese Ausführung fügt dem BODY
-Tag ein weiteres Element hinzu, das noch nicht analysiert wurde.BODY
und analysiert seinen Inhalt (den neu hinzugefügten Tag SCRIPT
), der das Skript lädt und seinen Inhalt ausführt.SCRIPT
-Elemente werden nur dann sofort ausgeführt, wenn Sie sie hinzufügen, nachdem Ihre Seite analysiert und bereits im Browser gerendert wurde. In Ihrem Fall ist das nicht der Fall. Das erste Skript wird sofort ausgeführt, und das dynamisch hinzugefügte Skript wird ausgeführt, wenn die Analyse ausgeführt wird.
Sie können asynchrone Vorgänge untereinander synchronisieren. Erstellen Sie eine rekursive Funktion, um eine Schleife darzustellen, und rufen Sie die nächste Operation auf, wenn der vorherige Vorgang abgeschlossen ist. Die folgende Funktion importiert Skripts in der gleichen Reihenfolge. Es wartet, bis ein Skript geladen ist, und wenn kein Fehler auftritt, wird mit dem nächsten fortgesetzt. Wenn ein Fehler auftritt, ruft er die Rückruffunktion mit dem Fehlerereignis auf. Wenn kein Fehler auftritt, ruft dieselbe Rückruffunktion mit Null auf, nachdem alle Skripts geladen wurden. Es reinigt auch nach sich selbst mit s.parentNode.removeChild(s)
.
function importScripts(scripts, callback) {
if (scripts.length === 0) {
if (callback !== undefined) {
callback(null);
}
}
var i = 0, s, r, e, l;
e = function(event) {
s.parentNode.removeChild(s);
if (callback !== undefined) {
callback(event);
}
};
l = function() {
s.parentNode.removeChild(s);
i++;
if (i < scripts.length) {
r();
return;
}
if (callback !== undefined) {
callback(null);
}
};
r = function() {
s = document.createElement("script");
s.src = scripts[i];
s.onerror = e;
s.onload = l;
document.head.appendChild(s);
};
r();
}