同步加载和执行javascript代码

Van*_*ing 41 javascript load synchronous

有没有办法像同步XMLHttpRequest一样以同步方式加载和执行javascript文件?

我目前正在使用同步XMLHttpRequest,然后使用eval,但调试该代码非常困难......

谢谢你的帮助!

更新

我现在试过这个:

的test.html

<html>
    <head>
        <script type="text/javascript">
            var s = document.createElement("script");
            s.setAttribute("src","script.js");
            document.head.appendChild(s);
            console.log("done");
        </script>
    </head>
    <body>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

的script.js

console.log("Hi");
Run Code Online (Sandbox Code Playgroud)

输出:完成嗨

所以它没有同步执行.任何想出"嗨"的想法首先出现?

更新2 其他示例

test.html(脚本标记内的代码)

var s = document.createElement("script");
s.setAttribute("src","script.js");
document.head.appendChild(s);
SayHi();
Run Code Online (Sandbox Code Playgroud)

的script.js

function SayHi(){
    console.log("hi");
}
Run Code Online (Sandbox Code Playgroud)

输出:未捕获的ReferenceError:未定义SayHi

hei*_*nob 21

如果你使用这个:

function loadScriptSync (src) {
    var s = document.createElement('script');
    s.src = src;
    s.type = "text/javascript";
    s.async = false;                                 // <-- this is important
    document.getElementsByTagName('head')[0].appendChild(s);
}
Run Code Online (Sandbox Code Playgroud)

你可以做你想要的(虽然在一个额外的脚本文件中划分)

test.html(脚本标记内的代码):

loadScriptSync("script.js");
loadScriptSync("sayhi.js"); // you have to put the invocation into another script file
Run Code Online (Sandbox Code Playgroud)

script.js:

function SayHi() {
     console.log("hi");
}
Run Code Online (Sandbox Code Playgroud)

sayhi.js:

SayHi();
Run Code Online (Sandbox Code Playgroud)

  • 这仅加载 ASYC.. 不同步 (5认同)
  • `loadScriptSync`不会内联执行它.使用`s.async = false`,scipts只是按顺序加载*.所以加载多个脚本可以保证它们按顺序执行. (3认同)

bjo*_*rnd 19

在DOM准备就绪后加载的所有脚本都是异步加载的.浏览器同步加载它们的唯一原因是write可以输出内容的功能.所以你可以使用脚本元素的onload回调来实现你想要的.

var s = document.createElement("script");
s.setAttribute("src","script.js");
s.onload = function(){
    console.log('Done');
}
document.head.appendChild(s);
Run Code Online (Sandbox Code Playgroud)

另一种方法是通过XHR加载js文件并在脚本元素中设置代码:

window.onload = function(){
    var req = new XMLHttpRequest();
    req.open('GET', "test.js", false);
    req.onreadystatechange = function(){
        if (req.readyState == 4) {
            var s = document.createElement("script");
            s.appendChild(document.createTextNode(req.responseText));
            document.head.appendChild(s);
        }
    };
    req.send(null);
}
Run Code Online (Sandbox Code Playgroud)

  • 这不是同步的;) (8认同)
  • 是的,但据我判断,没有其他解决方案。此外,您的问题是:“有什么想法让“Hi”首先出现吗?”,而不是“如何同步做到这一点?”。 (2认同)
  • 那我要用eval吗?问题的标题中提到要保持同步。 (2认同)

Jos*_*son 13

从类似的问题(/sf/answers/230493441/):

<script type="text/javascript">
  document.write('<script type="text/javascript" src="other.js"><\/script>');
</script>

<script type="text/javascript">
  functionFromOther();
</script>
Run Code Online (Sandbox Code Playgroud)

document.write'd脚本调用的代码需要在它自己的代码中,<script>或者它需要在window.onload()事件中.


Rob*_*nik 5

您的脚本确实同步执行

你的代码放在一起是:

1. create script element
2. set its attribute src
3. set its attribute deferred
4. display done...
Run Code Online (Sandbox Code Playgroud)

第一部分停止执行并将其移交给下一个脚本

5. script executes and displays Hi
Run Code Online (Sandbox Code Playgroud)

一切都非常同步......在Javascript中,一些代码完全执行,直到它执行到最后一行或将执行交给内部系统(如XHR或计时器).

当人们想要准备一些部分以便稍后执行时,他们会准备好setTimeout.即使超时比其余代码短,也会花费它执行的时间.代码完成执行后.例:

// some code
setTimeout(function(){ alert("I'm second alert"); }, 1);
longExecutionTask();
alert("I'm the first alert");
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,即使setTimeout设置为在1ms之后执行,它也不会启动,直到代码完成执行后结束显示一个alert框.你的情况也是如此.第一批代码必须在其他任何东西开始之前完成执行.

你为什么得到例外(在例子2中)

在我写完答案之后你已经添加了一些代码,所以这里有更多的信息.

添加脚本标记不会立即执行它.当HTML解析器到达SCRIPT您添加的元素时,将发生脚本加载+执行.它将在该点加载它并评估/执行其内容.

  1. HTML解析器开始解析您的文档
  2. HEAD正在解析并且其SCRIPT子标记被解析并执行.此执行会向BODY尚未解析的标记添加一个元素.
  3. 解析器继续BODY并解析其内容(新添加的SCRIPT标记),然后加载脚本并执行其内容.

SCRIPT只有在您的页面被解析并且已经在浏览器中呈现之后添加它们时,才会立即执行元素.在你的情况下,情况并非如此.第一个脚本立即执行,动态添加的脚本在分析到达时执行.

  • @RobertKoritnik,所以根据您的回答是不。 (2认同)