动态加载javascript - 等待执行?

时间:2016-12-12 10:58:38

标签: javascript

我正在动态加载多个javascript引用,并向DOM添加脚本标记。

感谢您帮助解释脚本加载行为。

我假设的是,当我将脚本元素附加到DOM时,脚本会被下载然后执行。但是当.onload事件被触发时?脚本一开始执行或完成执行后立即执行?如果第二个为真,那么如何等待脚本执行/初始化(我想执行回调,它会附加带有依赖于动态加载引用的脚本的附加html)?

要加载脚本我使用以下功能:

function recursiveInclude(scriptPathArray, callback) {
    if (scriptPathArray.length > 0) {
        var scriptPath = scriptPathArray[0];

        // check if script is already loaded if not load
        // this_loadedScriptList is one scope level up variable
        if (this_loadedScriptList.indexOf(scriptPath) > 0 == false) {
            var body        = document.getElementsByTagName('body')[0];
            var scriptElement       = document.createElement('script');
            scriptElement.type  = 'text/javascript';
            scriptElement.src       = scriptPath;

            // first script from the array will loaded as soon as body.appendChild function will be called
            // when script loads 'onload' event will fire next script loading
            // to this work properly first script from scriptPathArray has to be removed:
            scriptPathArray.shift();


            // if there are any other scripts to load, load them sequentially
            if (scriptPathArray.length > 0) {
                // then bind the event to the callback function
                // there are several events for cross browser compatibility
                // script.onreadystatechange = callback;

                scriptElement.onload = recursiveInclude(scriptPathArray, callback);                 
            } else {
                // if no other scripts to load - fire base callback;
                scriptElement.onload = callback;
            }    

            // fire the loading
            body.appendChild(scriptElement);

            // add script to loaded array.
            this_loadedScriptList.push(scriptPath);
        }           
    }

}

2 个答案:

答案 0 :(得分:1)

JavaScript既不是线程也不是事件中断。在其他任何事情发生之前执行漏洞脚本。捕获事件直到浏览器恢复控制。因此onload或任何其他事件只能在脚本执行完成之前或之后触发。实际上{/ 1}在执行后被解雇

firefox仍支持事件onload,但已从HTML5.1规范中删除。

你可以自己尝试一下:

beforescriptexecute

external.js:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
    <script>

      console.log('base script start');

      var script=document.createElement('script');
      script.onload = function() { console.log('onload fired'); }

      // MDN says:
      // This event was a proposal in an early version of the specification. Do not rely on it.
      // 
      script.addEventListener('beforescriptexecute', function () { console.log('beforescriptexecute fired'); });

      script.src = 'external.js';
      document.head.appendChild(script);

      console.log('waiting 3 seconds');
      timebase = Date.now();
      while((Date.now() - timebase) < 3000)
        ;
      console.log("base script end");
    </script>

</body>
</html>
  

基本脚本开始
  等待3秒
  基本脚本结束
  beforescriptexecute解雇了   外部开始...等待3秒
  外端
  onload炒了

MDN - beforescriptexecute

答案 1 :(得分:1)

你必须知道一个大问题。这样做意味着您远程加载代码。现代Web浏览器将加载文件并继续执行当前脚本,因为它们异步加载所有内容以提高性能。 (这适用于jQuery方法和手动动态脚本加载方法。)

这意味着如果您直接使用这些技巧,在您要求加载后,您将无法在下一行使用新加载的代码,因为它仍将加载。

实际上,您所能做的就是在加载脚本时使用事件来运行回调函数。

function loadScript(url, callback)
{        
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;

    script.onreadystatechange = callback;
    script.onload = callback;

    // Fire the loading
    head.appendChild(script);
}

然后编写如下代码:

var myCode = function() {
  ...
};

最后你可以运行它:

loadScript("the-remote-script.js", myCode);