36

I have the following script, where the first and third document.writeline are static and the second is generated:

<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 and Chrome will display before, during and after, while Internet Explorer first shows during and only then does it show before and after.

I've come across an article that states that I'm not the first to encounter this, but that hardly makes me feel any better.

Does anyone know how I can set the order to be deterministic in all browsers, or hack IE to work like all the other, sane browsers do?

Caveats: The code snippet is a very simple repro. It is generated on the server and the second script is the only thing that changes. It's a long script and the reason there are two scripts before and after it are so that the browser will cache them and the dynamic part of the code will be as small as possible. It may also appears many times in the same page with different generated code.

4

7 に答える 7

24

いいえ、これは Internet Explorer の動作です。

スクリプトを動的にアタッチすると、IE、Firefox、および Chrome はすべて非同期でスクリプトをダウンロードします。

Firefox と Chrome は、すべての非同期リクエストが返されるまで待機し、DOM にアタッチされている順序でスクリプトを実行しますが、IE はネットワーク経由で返された順序でスクリプトを実行します。

アラートは、外部の JavaScript ファイルよりも「取得」に時間がかからないため、表示されている動作を説明している可能性があります。

非同期スクリプトの読み込みに関するKristoffer Henriksson の投稿から:

このシナリオでは、IE と Firefox は両方のスクリプトをダウンロードしますが、Internet Explorer もダウンロードが完了した順序でスクリプトを実行しますが、Firefox はそれらを非同期的にダウンロードしますが、DOM に添付された順序で実行します。

Internet Explorer では、ネットワーク トラフィックやキャッシュなどによって実行順序が異なるため、スクリプトが互いに依存関係を持つことができないことを意味します。

Javascript ローダーの使用を検討してください。スクリプトの依存関係と実行順序を指定しながら、スクリプトを非同期でロードして速度を上げたり、ブラウザーの違いを滑らかにしたりすることができます。

これは、それらのいくつかのかなり良い概要です: Essential JavaScript: the top 5 script loader .

私は RequireJS と LabJS の両方を使用しました。私の意見では、LabJS はあまりこだわりがありません。

于 2008-09-18T17:35:19.390 に答える
5

私は自分の好みに合った答えを見つけました:

<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>

これにより、ページの読み込みが完了するまで、最中の両方の読み込みが延期されます。

私はこれが私が得ることができるほど良いと思います。うまくいけば、誰かがより良い答えを出すことができるでしょう。

于 2008-09-23T10:04:13.433 に答える
1

スクリプトで「onload」(または同様の) イベントを定義し、イベント関数に次のイベントを挿入することで、順次実行を強制できます。些細なことではありませんが、たくさんの例があります。

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

jQuery やプロトタイプなどの一般的なライブラリがこれに役立つと思います。

于 2008-09-19T11:03:49.713 に答える
1

このプレゼンテーションのスライド 25/26では、スクリプトを挿入するさまざまな方法の特徴について説明しています。IE がこれらのスクリプトを順番に実行する唯一のブラウザであることを示唆しています。他のすべてのブラウザーは、読み込みが完了した順序でそれらを実行します。1 つ以上が src の代わりにインライン js を持っている場合、IE でさえそれらを順番に実行しません。

提案されている方法の 1 つは、新しい 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);

2 番目のスクリプト セクションを生成するには、スクリプトを使用してそのコンテンツを生成し、パラメーターを渡します。

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

編集:私がサイトに掲載した記事の内容にもかかわらず、私のテストによると、ほとんどのブラウザーは、それぞれに src がある場合、document.write スクリプトを順番に実行することが示唆されているため、上記の方法が好ましいと思いますが、これを行うこともできます。 :

<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>

EDIT AGAIN (私自身や他の人へのコメントへの応答): あなたは既にあなたのページにスクリプトを生成しています。何をしていても、同じコード ブロックを生成する別のサーバー側スクリプトに移動できます。ページにパラメーターが必要な場合は、それらをクエリ文字列でスクリプトに渡します。

また、お勧めのように、インライン スクリプトを複数回生成している場合は、この同じ方法を使用できます。

<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>

しかし、これは間違った方法でアプローチしているように見え始めています。コードの大きなブロックを複数回生成している場合は、おそらくそれを単一の js 関数に置き換え、代わりに別のパラメーターで呼び出す必要があります...

于 2008-09-18T16:44:35.767 に答える
1

わかりました...その間...

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

後...

// 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>

ただし、これがにおいを出し始めている方法については同意する傾向があります。特に、動的に作成された js ファイルに "during" をコード生成して挿入できなかったのはなぜですか?

動的に生成されたスクリプトは、 2 番目のdocument.writeの関数内にあることに注意してください。 FF2、IE7でテスト済み

于 2008-09-18T17:05:08.527 に答える
0

どのようにそのことについて:

<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>
于 2009-04-02T20:23:38.943 に答える
0

提供するコード:

<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>

before.js で:

alert("Before");
callGeneratedContent();

after.js で:

alert("After");

生成された行を最初に配置する必要があります。そうしないと、関数定義を確認する前に before.js が実行されるため、FF が文句を言います。

于 2008-09-19T09:06:14.147 に答える