2009-04-02 4 views
2

Ich habe einige Nebenläufigkeitsprobleme mit einer Webseite, die ich baue. Grundsätzlich habe ich drei Skript-Dateien, die ich verwende einige Daten zu halten:Wie kann ich die Ausführungsreihenfolge von Javascript steuern?

script1.js:

var myValue = 1; 

script2.js:

var myValue = 2; 

Script3. js:

var myValue = 3; 

Und ich habe eine Seite, mypage.html, die im Grunde wie folgt aussieht:

<html> 
<script> 
    function get_number() 
    { 
    var script_file = GetQueryStringValue("run"); 
    e = document.createElement('script'); 
    e.type='text/javascript'; 
    e.src = script_file + ".js" 
    head.appendChild(e); 

    document.write(myValue); 
    } 
</script> 
<body onload="get_number()"> 
    <div onclick="get_number()">Click me!</div> 
</body> 
</html> 

Der Leitgedanke dieser Seite ist, dass Sie es wie folgt abfragen würde: mypage.html?run=script1 welche die get_number() Funktion sagen würde um dynamisch script1.js in mypage.htm einzufügen. Dann rufe ich get_number() an, um den aus dem Skript geladenen Wert anzuzeigen.

Nun, ich habe das oben auf das, was ich denke, sind die relevanten Teile reduziert und ich habe eine Menge Zeug offensichtlich weggelassen. Mein tatsächlicher Code lädt eine große Auswahl an Werten und ist interessanter ... Aber ich hoffe, dass mir jemand dabei helfen kann.

Was ich finde ist, dass in IE die Nummer korrekt angezeigt wird.

In Firefox, Chrome und Safari, bekomme ich eine Fehlermeldung, dass myValue nicht definiert ist. Wenn ich jedoch auf das von mir erstellte div. Click me klicke, wird die Nummer korrekt angezeigt. Ich weiß, dass ich die externe Javascript-Datei korrekt lade. Aber es ist einfach nicht rechtzeitig geladen, damit meine get_number() Funktion richtig funktioniert onload.

Nun gehackt ich meine Datei ein wenig nach oben, so dass die get_number Funktion wie folgt aussieht:

function get_number() 
{ 
    var script_file = GetQueryStringValue("run"); 
    e = document.createElement('script'); 
    e.type='text/javascript'; 
    e.src = script_file + ".js" 
    head.appendChild(e); 

    setTimeout(function() { document.write(myValue), 10 }); 
} 

Die setTimeout Verzögerungen genug für den DOM aktualisiert werden und die Javascript in den meisten Fällen geladen werden. Aber das ist ein totaler Hack. Firefox tendiert dazu, diesen "verbesserten" Code ständig korrekt zu laden, während Chrome und Safari den Wert in etwa 50% der Zeit erreichen.

Also, ich denke, ich frage mich, gibt es einen besseren Weg, um das zu erreichen, was ich hier versuche? Es ist sehr wichtig, dass der Wert extern (durch die Abfragezeichenfolge) gesteuert wird, aber abgesehen von dieser Anforderung bin ich sehr flexibel.

+0

http://www.infoq.com/articles/stratifiedjs – n611x007

Antwort

3

Könnten Sie vielleicht einen Funktionsaufruf an das Skript-Dateien hinzufügen, so dass, wenn sie ausgeführt sind, rufen sie die Funktion, die Ihre

document.write(myValue); 

so geht das script1.js wäre

var myValue = 1; 
scriptLoaded(); 

und Ihre Hauptdatei würde:

function scriptLoaded(){ 
    document.write(myValue); 
} 
+1

Dies ist die Lösung, mit der ich ging, weil es sich als so einfach erwies. Ich fühle mich etwas albern, dass ich selbst nicht daran gedacht habe! Danke für die anderen Antworten, obwohl. Sie waren alle tatsächlich bearbeitbar und hätten mir das Problem gelöst. –

6

Diese Methode zum dynamischen Laden von Skriptdateien mit DOM-Methoden wie head.appendChild ist asynchron. Dies bedeutet, dass die Seite nicht darauf wartet, dass sie geladen wird, bevor weiterer Code ausgeführt wird. Wenn Sie dieses asynchrone Verhalten nicht möchten, können Sie sie mit regulären Elementen in Ihrem HTML laden, oder Sie könnten mit einem 'synchronen' XMLHttpRequest herumfummeln, um es zu erhalten und eval(), um es auszuführen.

Wahrscheinlich möchten Sie das jedoch nicht tun, da das asynchrone Laden die gesamte Seite sowieso schneller macht. Sie müssen wahrscheinlich nur eine Logik hinzufügen, die darauf wartet, dass das dynamisch geladene Skript geladen wurde, bevor Sie mit dem nächsten Bit Code fortfahren.Dies kann jedoch das Abfragen mit setInterval() beinhalten, bis Sie feststellen, dass eine Variable aus dem eingeschlossenen Skript definiert wurde. Oder Sie könnten Code in das enthaltene Skript einfügen, das eine Methode für das aufruft, was darauf gewartet hat.

Oder könnten Sie betrachten, wie jQuery macht etwas Ähnliches, suchen Sie nach, wo die Ajax-Methode definiert ist, speziell diese Teile ...

var script = document.createElement("script"); 

// then later ... 

script.onload = script.onreadystatechange = function(){ 
    if (!done && (!this.readyState || 
    this.readyState == "loaded" || this.readyState == "complete")) { 

     // do processing 
      head.removeChild(script); 
    } 
}; 

// ... 

head.appendChild(script); 
+0

Haben Sie das Wort asynchrone denken wird von den meisten Menschen falsch eigentlich werden? Ich meine, du würdest denken, dass asynchron bedeutet, dass Dinge nicht zusammen oder gleichzeitig passieren, das wäre synchron. Aber die Leute benutzen es mit der entgegengesetzten Bedeutung. – dezman

+0

Glaub mir nicht, dass ich jemals gesehen habe, dass Leute es mit der entgegengesetzten Bedeutung benutzen - worauf hast du dich bezogen? Übrigens, Polling, wie in dieser Antwort beschrieben, ist wahrscheinlich nicht mehr notwendig, da XMLHttpRequest besser funktioniert und jetzt mehr unterstützt wird. – thomasrutter

Verwandte Themen