2009-12-18 3 views
25

Ich benutze dynamisches Skript, um die Dauer der anfänglichen Seitenladung zu reduzieren. Um sicherzustellen, dass die Funktionen und Objekte, die von einem Skript definiert werden, zugänglich sind, muss ich sicherstellen, dass das Skript vollständig geladen wurde.Kann script.readyState vertrauenswürdig sein, um das Ende des Ladens von dynamischen Skripten zu erkennen?

Ich habe my own Javascript library zu diesem Zweck entwickelt, und so eine ganze Menge Forschung zu diesem Thema gemacht, zu studieren, wie es in verschiedenen Bibliotheken getan wird. Während einer Diskussion zu diesem Problem, Kyle Simpson, der Autor von LABjs vorsah:

LABjs (und vielen anderen Ladern) gesetzt beide „onload“ und „onreadystatechange“ auf allen Script-Elemente, wohl wissend, dass werden einige Browser ein Feuer, und einige das andere Feuer ...

Sie können ein Beispiel dafür in the current version of jQuery as of this writing, v1.3.2 finden:

// Attach handlers for all browsers 
script.onload = script.onreadystatechange = function(){ 
    if (!done && (!this.readyState || 
    this.readyState == "loaded" || this.readyState == "complete")) { 
     done = true; 
     success(); 
     complete(); 

     // Handle memory leak in IE 
     script.onload = script.onreadystatechange = null; 
     head.removeChild(script); 
    } 
}; 

Das ist der Stand der Technik, aber während der Analyse eines seltsamen Verhaltens in Opera 9.64 kam ich zu dem Schluss, dass der Onload-Callback mit dieser Technik zu früh gefeuert wurde.

Ich werde meine eigenen Ergebnisse in der Antwort auf diese Frage veröffentlichen, und möchte weitere Beweise und Rückmeldungen von der Gemeinschaft sammeln.

+0

Wer findet den aktuellen Code im jQuery 1.x-master-Zweig? Es sieht so aus, als hätten sie '.readystatechange' und' .onload' nicht mehr verwendet und sie durch Versprechen ersetzt? [Clicky] (https://github.com/jquery/jquery/blob/1.x-master/src/ajax.js) – Campbeln

Antwort

7

In Opera kann der Eigenschaft script.readyState nicht vertraut werden. Beispielsweise kann der readyState "loaded" ausgelöst werden, bevor das Skript in Opera 9.64 ausgeführt wird.

Ich führte the same test in Opera 9.64 und Opera 10, mit unterschiedlichen Ergebnissen.

In Opera 9.64 wird der onreadystatechange -Handler zweimal ausgelöst, einmal vor und einmal nach dem Ausführen des Skripts. Die Readystate Eigenschaft ist „geladen“ in beiden Fällen, was bedeutet, dass dieser Wert nicht das Ende des Skripts Ladens vertraut werden kann, erkennen:

# Fri Dec 18 2009 17:54:43 GMT+0100 
# Opera/9.64 (Windows NT 5.1; U; en) Presto/2.1.1 
Test for script.readyState behavior started 
Added script with onreadystatechange handler 
readystatechange: loaded 
test1.js: Start 
test1.js: Start of closure 
test1.js: End of closure 
readystatechange: loaded 

In Opera 10, der onreadystatechange Handler immer noch mit dem Wert gefeuert wird zweimal " geladen“, aber beiden Male nach dem Skript ausgeführt:

# Fri Dec 18 2009 18:09:58 GMT+0100 
# Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.10 
Test for script.readyState behavior started 
Added script with onreadystatechange handler 
test1.js: Start 
test1.js: Start of closure 
test1.js: End of closure 
readystatechange: loaded 
readystatechange: loaded 

Diese unterschiedlichen Verhaltensweisen zeigen, dass onreadystatechange keine zuverlässige Art und Weise ist das Ende eines Skripts Laden in Opera zu erkennen. Da Opera auch den Onload-Listener unterstützt, sollte stattdessen dieser andere Mechanismus verwendet werden.

Basierend auf den Ergebnissen dieser Tests sollte onreadystatechange nur verwendet werden, um das Ende des Ladens von Skripts in Internet Explorer zu erkennen, und sollte nicht in anderen Browsern festgelegt werden.

+0

Zumindest können Sie das erste Ereignis ignorieren. –

+2

@Justin Johnson, die peinlich erscheint, werden Sie die "geladenen" Ereignisse zählen, aber nur in Opera? –

3

In Firefox, Safari und Chrome wird der onreadystatechange Handler nevers aufgerufen.

Ich habe einen kurzen Testfall, ein dynamisches Skript nur mit dem onreadystatechange-Handler-Set zu erstellen:

<script type="text/javascript" language="javascript"> 
bezen.log.info(new Date(),true); 
bezen.log.info(navigator.userAgent,true); 

// Activate logs 
bezen.log.on(); 
bezen.log.info('Test for script.readyState behavior started'); 

var script = document.createElement('script'); 
script.src = 'test1.js'; 
script.onreadystatechange = function(){ 
    bezen.log.info('readystatechange: '+script.readyState); 
}; 
document.body.appendChild(script); 
bezen.log.info('Added script with onreadystatechange handler'); 
</script> 

ich den Test auf einer lokalen Datei in Firefox 2, 3 Firefox ausgeführt, Firefox 3.5, Safari 3, Safari 4 und Chrome 3 und erhielt ähnliche Ergebnisse (hier die Protokolle aufgezeichnet in FF 3.5):

Fri Dec 18 2009 17:53:58 GMT+0100 
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 
Test for script.readyState behavior started 
Added script with onreadystatechange handler 
test1.js: Start 
test1.js: Start of closure 
test1.js: End of closure 

Die onreadystatechange nie aufgerufen wird. In diesen Browsern ist nur der Onload-Listener nützlich, um das Ende des Ladens eines Scripts zu erkennen. Die Änderung des Status onreadystate ist nicht erforderlich.

1

In Internet Explorer wird der onreadystatechange-Handler wie erwartet nach dem Ende des Skripts ausgelöst.

führte ich die same test in Internet Explorer 6, Internet Explorer 7 und Internet Explorer 8, mit ähnlichen Ergebnissen in diesen drei Browsern (hier die in Internet aufgezeichnet Protokolle Explorer 6):

Fri Dec 18 18:14:51 UTC+0100 2009 
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729) 
Test for script.readyState behavior started 
Added script with onreadystatechange handler 
test1.js: Start 
test1.js: Start of closure 
test1.js: End of closure 
readystatechange: complete 

hier mit einem Testen Sie mit einer lokalen Datei, der readyState ist immer "complete", und es war immer noch dasselbe nach mehreren Seitenaktualisierungen.

Wie jedoch unter this post by Nicholas C. Zakas erwähnt, können Sie unter verschiedenen Umständen auch "geladen" und "abgeschlossen" oder nur "geladen" beobachten.

1

Ich habe festgestellt, dass Internet Explorer (Testen in 9) nicht immer Ihr Skript bereit, wenn readyState === "geladen". Ich hatte Erfolg mit diesem Event-Handler (in 9 natürlich) onactivate. Ich zog mir vorher die Haare aus.

0

Ähnliche Ergebnisse in Chrome.

Hat onready nicht nehmen ...

Gerade onload und onerror.

Verwandte Themen