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

时间:2020-03-06 14:22:14  来源:igfitidea点击:

我有以下脚本,其中第一个和第三个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会在显示期间和之后显示,然后才显示。

我遇到过一篇文章,指出我不是第一个遇到这种情况的人,但这几乎没有使我感觉更好。

有谁知道我如何在所有浏览器中将顺序设置为确定性,或者如何使IE像其他所有正常的浏览器一样工作?

注意事项:代码段非常简单。它是在服务器上生成的,第二个脚本是唯一更改的东西。这是一个很长的脚本,其原因是前后有两个脚本,以便浏览器将它们缓存,并且代码的动态部分将尽可能地小。它可能还会在同一页面中以不同的生成代码多次出现。

解决方案

本演示文稿的幻灯片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函数替换它,并使用不同的参数调用它...

好...在...期间

// 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中测试

不,这是Internet Explorer的行为。

如果我们动态添加脚本,则IE,Firefox和Chrome都将以异步方式下载脚本。

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

由于警报花费的时间比外部javascript文件花费的时间少,因此很可能可以解释我们所看到的行为。

从Kristoffer Henriksson的关于异步脚本加载的主题的文章中:

In this scenario IE and Firefox will
  download both scripts but Internet
  Explorer will also execute them in the
  order they finish downloading in
  whereas Firefox downloads them
  asynchronously but still executes them
  in the order they are attached in the
  DOM.
  
  In Internet Explorer this means your
  scripts cannot have dependancies on
  one another as the execution order
  will vary depending on network
  traffic, caches, etc.

考虑使用Javascript加载程序。它可以让我们指定脚本依赖性和执行顺序,同时还可以异步加载脚本以提高速度并消除浏览器的某些差异。

这是其中的一些很好的概述:基本JavaScript:前五个脚本加载器。

我已经使用了RequireJS和LabJS。在我看来,LabJS显得有些自以为是。

提供的代码:

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

我们可以通过在脚本上定义" onload"(或者类似的)事件并在事件函数中注入下一个事件来强制执行安全性。
这不是小事,但是有很多例子,这里是一个。

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

我认为流行的库(例如jQuery或者原型)可以帮助解决此问题。

我发现了更多我喜欢的答案:

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

这将在页面完成加载之前和之后延迟加载。

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

那个怎么样:

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