Load and execute javascript code SYNCHRONOUSLY

房东的猫 提交于 2019-12-29 03:18:09

问题


Is there a way to load and execute a javascript file in a synchronous way just like a synchronous XMLHttpRequest?

I'm currently using a sync XMLHttpRequest and then eval for this, but debugging that code is very difficult...

Thanks for your help!

Update

I tried this now:

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>

script.js

console.log("Hi");

Output: done Hi

So it was not executed synchronously. Any idea to make "Hi" appear first?

Update 2 Other example

test.html (code inside a script tag)

var s = document.createElement("script");
s.setAttribute("src","script.js");
document.head.appendChild(s);
SayHi();

script.js

function SayHi(){
    console.log("hi");
}

Output: Uncaught ReferenceError: SayHi is not defined


回答1:


If you use this:

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);
}

You can do what you want (although divided up in an additional script file)

test.html (code inside a script tag):

loadScriptSync("script.js");
loadScriptSync("sayhi.js"); // you have to put the invocation into another script file

script.js:

function SayHi() {
     console.log("hi");
}

sayhi.js:

SayHi();



回答2:


All scripts which are loaded after DOM is ready are loaded asynchronously. The only reason for browser to load them synchronously is function write which can output something. So you can use onload callback of the script element to achieve what you want.

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

Another way is to load js-file via XHR and set code inside the script element:

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);
}



回答3:


From a similar question ( https://stackoverflow.com/a/3292763/235179 ):

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

<script type="text/javascript">
  functionFromOther();
</script>

Either the code called from the document.write'd script needs to be in it's own <script> or it needs to be in the window.onload() event.




回答4:


Your scripts do execute synchronously

your code if put together is:

1. create script element
2. set its attribute src
3. set its attribute deferred
4. display done...

this first part stops execution and hands it over to next script

5. script executes and displays Hi

Everything is very much synchronous... In Javascript some code is executed completely until it executes to the last line or hands execution over to internal systems (like XHR or timer).

When one would like to put prepare some parts to execute later on, they prepare it with setTimeout. Even if timeout is shorter than the rest of the code will take that's the time it will execute. After code has finished executing. Example:

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

In the above code even if setTimeout is set to execute after 1ms it won't start until the code after it finishes execution which ends with displaying an alert box. The same happens in your case. The first batch of code has to finish executing before anything else can start.

Why you're getting exception (in example 2)

You've added some more code after I've written my answer so here goes some more info.

Adding a script tag will not immediately execute it. Script loading+execution will happen when HTML parser will get to the SCRIPT element you added. It will load it at that point and evaluate/execute its content.

  1. HTML parser starts parsing your document
  2. HEAD is being parsed and its SCRIPT child tag gets parsed and executed. This execution adds one more element to BODY tag that hasn't been parsed yet.
  3. Parser moves on to BODY and parses its content (the newly added SCRIPT tag) which then loads the script and executes its content.

SCRIPT elements get immediately executed only when you they're added after your page has been parsed and is already rendered in browser. In your case that is not the case. The first script executes immediately and the dynamically added one executes when parses gets to it.




回答5:


You can synchronize asynchronous operations among themself. Create recursive function to represent a loop and call the next operation when previous finish. The following function imports scripts in order with the similar technique. It waits a script to be loaded and if there is no error continues with the next. If an error occur it calls the callback function with the error event and if there is no error - calls the same callback function with null after all scripts are loaded. It also cleans after itself with s.parentNode.removeChild(s).

function importScripts(scripts, callback) {
    if (scripts.length === 0) {
        if (callback !== undefined) {
            callback(null);
        }
        return;
    }
    var i = 0, s, r, e, l;
    e = function(event) {
        s.parentNode.removeChild(s);
        if (callback !== undefined) {
            callback(event);
        }
    };
    l = function() {
        s.parentNode.removeChild(s);
        i++;
        if (i < scripts.length) {
            r();
            return;
        }
        if (callback !== undefined) {
            callback(null);
        }
    };
    r = function() {
        s = document.createElement("script");
        s.src = scripts[i];
        s.onerror = e;
        s.onload = l;
        document.head.appendChild(s);
    };
    r();
}


来源:https://stackoverflow.com/questions/6074833/load-and-execute-javascript-code-synchronously

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!