2008-09-18 9 views
36

Je le script suivant, où le premier et le troisième document.writeline sont statiques et le second est généré:document.write script en ligne Ordre d'exécution de JavaScript

<script language="javascript" type="text/javascript"> 
document.write("<script language='javascript' type='text/javascript' src='before.js'><\/sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript'>alert('during');<\/sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript' src='after.js'><\/sc" + "ript>"); 
</script> 

Firefox et Chrome affiche avant, pendant et après, tandis que Internet Explorer montre d'abord pendant et seulement alors il montre avant et après.

Je suis tombé sur an article that states que je ne suis pas le premier à rencontrer cela, mais cela ne me fait guère me sentir mieux.

Est-ce que quelqu'un sait comment je peux définir l'ordre d'être déterministe dans tous les navigateurs, ou pirater IE pour fonctionner comme tous les autres navigateurs sane?

Mises en garde: L'extrait de code est un repro très simple. Il est généré sur le serveur et le deuxième script est la seule chose qui change. C'est un long script et la raison pour laquelle il y a deux scripts avant et après est que le navigateur les mettra en cache et la partie dynamique du code sera aussi petite que possible. Il peut également apparaître plusieurs fois dans la même page avec le code généré différent.

+0

Doit lire: http://html5rocks.com/en/tutorials/speed/script-loading – Pacerier

Répondre

5

J'ai trouvé une réponse plus à mon goût:

<script language="javascript" type="text/javascript"> 
document.write("<script language='javascript' type='text/javascript' src='before.js'><\/sc" + "ript>"); 
document.write("<script defer language='javascript' type='text/javascript'>alert('during');<\/sc" + "ript>"); 
document.write("<script defer language='javascript' type='text/javascript' src='after.js'><\/sc" + "ript>"); 
</script> 

Cela différer le chargement des deux pendant et après jusqu'à ce que la page a terminé le chargement. Je pense que c'est aussi bon que je peux l'obtenir. J'espère que quelqu'un sera en mesure de donner une meilleure réponse.

+6

Internet Explorer exécute des scripts en ligne avant les scripts externes. Pour obtenir un ordre cohérent, déplacez le code en ligne vers un fichier externe. –

1

Les diapositives 25/26 de this presentation traitent des caractéristiques des différentes méthodes d'insertion de scripts. Il suggère que IE est le seul navigateur qui va exécuter ces scripts dans l'ordre. Tous les autres navigateurs les exécuteront dans l'ordre de fin du chargement. Même IE ne les exécutera pas dans l'ordre si un ou plusieurs ont js en ligne au lieu d'un src.

L'une des méthodes proposées consiste à insérer un nouvel élément DOM:

var se1 = document.createElement('script'); 
se1.src = 'a.js'; 

var se2 = document.createElement('script'); 
se2.src = 'b.js'; 

var se3 = document.createElement('script'); 
se3.src = 'c.js'; 

var head = document.getElementsByTagName('head')[0] 
head.appendChild(se1); 
head.appendChild(se2); 
head.appendChild(se3); 

Pour faire la deuxième section de script généré, vous pouvez utiliser un script pour générer ce contenu et transmettre les paramètres:

se2.src = 'generateScript.php?params=' + someParam; 

EDIT: Malgré ce que dit l'article que j'ai cité, mes tests suggèrent que la plupart des navigateurs exécuteront vos scripts document.write s'ils ont chacun un src, donc bien que je pense que la méthode ci-dessus est préférée, vous pouvez le faire ainsi:

<script language="javascript" type="text/javascript"> 
document.write("<script type='text/javascript' src='before.js'><\/sc" + "ript>"); 
document.write("<script type='text/javascript' src='during.php?params=" + params + "'><\/sc" + "ript>"); 
document.write("<script type='text/javascript' src='after.js'><\/sc" + "ript>"); 
</script> 

ÉDITER DE NOUVEAU (réponse aux commentaires pour moi et les autres): Vous générez déjà le script sur votre page. Tout ce que vous faites peut être déplacé vers un autre script côté serveur qui génère le même bloc de code. Si vous avez besoin de paramètres sur votre page, transmettez-les au script dans la chaîne de requête.

, vous pouvez également utiliser cette même méthode si, comme vous le suggérez, vous générez le script en ligne plusieurs fois:

<script language="javascript" type="text/javascript"> 
document.write("<script type='text/javascript' src='before.js'><\/sc" + "ript>"); 
document.write("<script type='text/javascript' src='during.php?params=" + params1 + "'><\/sc" + "ript>"); 
document.write("<script type='text/javascript' src='during.php?params=" + params2 + "'><\/sc" + "ript>"); 
document.write("<script type='text/javascript' src='during.php?params=" + params3 + "'><\/sc" + "ript>"); 
document.write("<script type='text/javascript' src='after.js'><\/sc" + "ript>"); 
</script> 

Cependant, cela commence à regarder comme si vous abordez ce dans le mauvais sens . Si vous générez un grand bloc de code plusieurs fois alors vous devriez probablement le remplacer par une seule fonction js et l'appeler avec des paramètres différents à la place ...

+0

'pendant' est un morceau très long de l'écriture, donc je peux » t résumez-le à une demande get simple ... –

+0

@Omer: Vous l'avez déjà résumée à une "demande de requête simple" ... Comment la générez-vous maintenant pour la mettre en ligne? Quoi que vous fassiez maintenant, vous pouvez le faire sur une autre page, mais ne renvoyez que le js et non le reste de la page. – Prestaul

+0

le code de démo que j'ai donné est un repro très simplifié du problème. le code que j'ai écrit est celui qui est généré et le fichier inclus sont de sorte que le navigateur les mettra en cache et aura besoin de moins de temps pour charger la page. –

1

Ok ... pendant ...

// During.js 
during[fish](); 

après ...

// After.js 
alert("After"); 
fish++ 

HTML

<!-- some html --> 
<script language="javascript" type="text/javascript"> 
document.write("<script language='javascript' type='text/javascript' src='before.js'></sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript'>during[" + fish + "] = function(){alert('During!' + fish);}</sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript' src='during.js'></sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript' src='after.js'></sc" + "ript>"); 
</script> 
<!-- some other html --> 
<script language="javascript" type="text/javascript"> 
document.write("<script language='javascript' type='text/javascript' src='before.js'></sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript'>during[" + fish + "] = function(){alert('During!' + fish);}</sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript' src='during.js'></sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript' src='after.js'></sc" + "ript>"); 
</script> 

Je suis plutôt d'accord sur la façon dont cela commence à sentir, cependant. En particulier, pourquoi ne pourriez-vous pas coder le "pendant" dans un fichier js créé dynamiquement, et l'insérer?

Notez que le script généré dynamiquement va intérieur la fonction dans la seconde document.write.
Testé en FF2, IE7

24

Non, c'est le comportement d'Internet Explorer.

Si vous attachez dynamiquement des scripts, IE, Firefox et Chrome téléchargeront tous les scripts de manière asynchrone. Firefox et Chrome attendent que toutes les demandes asynchrones reviennent et exécutent les scripts dans l'ordre dans lequel ils sont attachés dans le DOM, mais IE exécute les scripts dans l'ordre où ils sont renvoyés sur le réseau.

Comme l'alerte prend moins de temps pour "récupérer" qu'un fichier javascript externe, cela explique probablement le comportement que vous voyez.

De Kristoffer Henriksson de post on the subject of asynchronous script loading:

Dans ce scénario IE et Firefox télécharger les scripts mais Internet Explorateur également les exécuter dans le ordre dans lequel ils finissent le téléchargement dans alors que Firefox les télécharge de manière asynchrone, mais les exécute toujours dans l'ordre dans lequel ils sont attachés dans le DOM .

Dans Internet Explorer cela signifie que votre scripts ne peuvent pas avoir sur dépendances les uns des autres que l'ordre d'exécution varie en fonction du réseau trafic, caches, etc.

Pensez à utiliser un chargeur Javascript. Il vous permettra de spécifier les dépendances de script et l'ordre d'exécution tout en chargeant vos scripts de manière asynchrone pour la vitesse ainsi que de lisser certaines différences du navigateur.

Ceci est un assez bon aperçu de quelques-uns d'entre eux: Essential JavaScript: the top five script loaders.

J'ai utilisé RequireJS et LabJS. À mon avis, LabJS est un peu moins opiniâtre.

0

Code pour fournir:

<script language="javascript" type="text/javascript"> 
document.write("<script language='javascript' type='text/javascript'>function callGeneratedContent() { alert('during'); }<\x2Fscript>"); 
document.write("<script language='javascript' type='text/javascript' src='before.js'><\x2Fscript>"); 
document.write("<script language='javascript' type='text/javascript' src='after.js'><\x2Fscript>"); 
</script> 

En before.js:

alert("Before"); 
callGeneratedContent(); 

En après.js:

alert("After"); 

Vous devez mettre la première ligne générée, sinon FF va se plaindre parce qu'il exécute before.js avant de voir la définition de la fonction.

+0

s'il vous plaît voir la mise en garde de la réponse de Dustman. –

1

Vous pouvez forcer l'exécution sécuentielle en définissant des événements "onload" (ou similaires) sur les scripts et en injectant le suivant dans la fonction d'événement. Ce n'est pas trivial, mais il y a beaucoup d'exemples là-bas, en voici un.

http://www.phpied.com/javascript-include-ready-onload/

Je pense que les bibliothèques populaires comme jQuery ou un prototype peut aider.

0

Que diriez-vous que:

<script> 
document.write("<script src='before.js'><\/script>"); 
</script> 

<script > 
document.write("<script>alert('during');<\/script>"); 
</script> 

<script> 
document.write("<script src='after.js'><\/script>"); 
</script> 
Questions connexes