JavaScript document.write内联脚本执行顺序

时间:2008-09-18 16:25:53

标签: javascript cross-browser browser

我有以下脚本,第一个和第三个document.writeline是静态的,第二个是

<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和Chrome将在之前显示,在之前显示,在之后显示,而Internet Explorer首先在期间显示且仅显示然后在之前显示,在之后显示

我遇到an article that states,我不是第一个遇到这种情况的人,但这几乎让我感觉不到更好。

是否有人知道我如何将订单设置为在所有浏览器中具有确定性,或者黑客IE浏览器与所有其他浏览器一样工作?

警告:代码段是一个非常简单的repro。它是在服务器上生成的,第二个脚本是唯一发生变化的脚本。这是一个很长的脚本,并且之前和之后有两个脚本的原因是浏览器将缓存它们,并且代码的动态部分将尽可能小。它也可能在具有不同生成代码的同一页面中多次出现。

7 个答案:

答案 0 :(得分:24)

不,这是Internet Explorer的行为。

如果您动态附加脚本,IE,Firefox和Chrome都会以异步方式下载脚本。

Firefox和Chrome将等待所有异步请求返回,然后按照它们在DOM中附加的顺序执行脚本,但IE按照通过网络返回的顺序执行脚本。

由于警报比外部javascript文件花费更少的时间来“检索”,这可能解释了您所看到的行为。

来自Kristoffer Henriksson的post on the subject of asynchronous script loading

  

在这种情况下,IE和Firefox会   下载两个脚本但Internet   资源管理器也将执行它们   命令他们完成下载   而Firefox下载它们   异步但仍然执行它们   按照它们附在的顺序   DOM。

     

在Internet Explorer中,这意味着您的   脚本不能具有依赖性   彼此作为执行顺序   将根据网络而有所不同   交通,缓存等。

考虑使用Javascript加载器。它可以让您指定脚本依赖性和执行顺序,同时还可以异步加载脚本以提高速度,并平滑一些浏览器差异。

这是对其中一些的很好的概述:Essential JavaScript: the top five script loaders

我已经使用过RequireJS和LabJS。在我看来,LabJS不那么自以为是。

答案 1 :(得分: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>

这将推迟在之后加载,直到页面加载完毕。

我认为这是我能得到的最好的。希望有人能够给出更好的答案。

答案 2 :(得分:1)

this presentation的幻灯片25/26讨论了插入脚本的不同方法的特征。它表明IE是唯一按顺序执行这些脚本的浏览器。所有其他浏览器将按照完成加载的顺序执行它们。如果一个或多个内联js而不是src,IE甚至不会按顺序执行它们。

建议的方法之一是插入一个新的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);

要生成第二个脚本部分,您可以使用脚本生成该内容并传递参数:

se2.src = 'generateScript.php?params=' + someParam;
编辑:尽管我选择的文章说的是,我的测试表明大多数浏览器会按顺序执行你的document.write脚本,如果他们每个都有一个src,所以虽然我认为上面的方法是首选,你可以做这也是:

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

再次编辑(对自己和他人的评论回复):您已经在页面上生成了脚本。无论您正在做什么,都可以转移到生成相同代码块的另一个服务器端脚本。如果您需要页面上的参数,请将它们传递给查询字符串中的脚本。

此外,如果您按照建议多次生成内联脚本,则可以使用相同的方法:

<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函数替换它并用不同的params调用它...

答案 3 :(得分: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文件,并插入?

请注意,动态生成的脚本在第二个 document.write中的内部功能。
测试了FF2,IE7

答案 4 :(得分:1)

您可以通过在脚本上定义“onload”(或类似)事件来强制执行secuential执行,并在事件函数中注入下一个事件。 这不是微不足道的,但有很多例子,这里有一个。

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

我认为像jQuery或原型这样的流行图书馆可以为此提供帮助。

答案 5 :(得分: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");

你必须首先放置生成的行,否则FF会抱怨,因为它在看到函数定义之前执行before.js。

答案 6 :(得分: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>