【问题标题】:function fails to load a script函数无法加载脚本
【发布时间】:2016-12-19 12:59:12
【问题描述】:

我正在使用以下函数将脚本加载到 HTML 文件中,

function addScript(src){
 var script = document.createElement('script');
 var location = "javascripts/";
 src =location + src;
 script.setAttribute('src', src);
 document.body.appendChild(script);
};

addScript('george.js');
addScript('fred.js');
addScript('main.js')

但是,它似乎能够加载太大的文件(如 200 行)。例如,如果 george.js 有一个 George 类,并且文件太长,则尝试创建新的 George() 将失败。

我确信这是一个加载大小问题,原因如下:

1) 如果我从 george.js 中注释掉几乎所有内容,新 George 仍然会失败。

2) 如果我从 george.js 中删除任何 10 个函数,new George 就会成功。

3) 如果我将新 George 拆分为 2 个文件,它会成功

4)。如果我在 fred.js 中添加大量 cmets,new Fred 会失败。

5)明确一点,george.js 可以

function George(){};

我可以打电话:

var george = new George();

在我的文件中。但是,如果 george.js 变成了

function George(){};

/* 
(Insert hundreds of lines of comments here)
*/

代码

var george = new George();

会导致

ReferenceError: George is not defined

为什么这个函数在加载大约 200 行的文件时遇到问题?我能做些什么来解决这个问题?

编辑:

尝试使用 window.setTimeout 函数。

AfterTimeout = function(){
  var george = new George();
}


window.setTimeout(AfterTimeout , 3000);

这似乎确实有效。

我最终通过设置 script.async = false; 使其工作。

【问题讨论】:

  • fred 或 george 是否依赖访问 DOM 中的任何内容?
  • 开发者工具控制台中的任何错误
  • Derp,我不确定你的意思。
  • 此外,除了“未声明 HTML 文档的字符编码”和“参考错误:未定义 Fred”之外,没有其他错误
  • 我的猜测是因为加载一个 JavaScript 文件需要时间,你会希望仅在该文件完全加载后才使用这些函数。尝试在几秒钟内运行 setTimeout,看看是否是导致问题的原因。

标签: javascript html


【解决方案1】:

如果不查看 fred 或 george 的内容,很难看出错误是什么,但我可以想到两件事可能导致您的错误:

1) 如果您正在访问 DOM 元素(例如 html 中的元素),则需要等到 HTML 元素完成加载。您可以通过将代码包装在 DOMContentLoaded 回调中来做到这一点

例如

document.addEventListener("DOMContentLoaded", function() {
  function addScript(src){
    var script = document.createElement('script');
    var location = "javascripts/";
    src =location + src;
    script.setAttribute('src', src);
    document.body.appendChild(script);
  };

  addScript('george.js');
  addScript('fred.js');
  addScript('main.js')
});

2) 您需要注意的第二件事是,如果您像这样动态添加脚本,它可能本质上是异步的。如果由于依赖关系需要顺序调用脚本,可以尝试将 async 属性设置为 false

例如

script.setAttribute('async', false);

【讨论】:

    【解决方案2】:

    通过自己创建 DOM 元素并将它们附加到您的文档中,您正在尝试异步加载 Javascript 文件。如果 george.js 在调用 var george = new George(); 之前完成加载,那么这次你很幸运,不会有任何问题。但是如果 george.js 真的很大,或者是通过慢速网络连接获取的,那么在您尝试在代码中创建新的 George 之前,它很可能无法加载并准备好。

    加载脚本以及在保证加载脚本时调用回调的最快方法可能是使用 jQuery 的 getScript() 函数。正确的方法可能是使用webpackbrowserify 之类的东西来正确识别和处理您编写的不同源文件之间的所有依赖关系。

    here 是一个非常好的讨论细节的答案。

    【讨论】:

    • 如果脚本在不同的服务器上,getScript 会起作用吗?
    • 我相信你是对的。我可能应该使用其中之一。你有什么推荐的吗?
    【解决方案3】:

    您必须等待脚本完全加载才能使用其代码。 在script 上捕获事件onload 然后执行。使用这样的东西:

    var writeScripts = function (scripts, callback) {
        if(scripts.length==0) callback && callback();
        var src = scripts.shift();
        var s = document.createElement('script');
        s.type = "text/javascript";
        s.src = src;
        if(s.addEventListener) {
            s.addEventListener('load', function (e) { writeScripts(scripts, callback); }, false);
        } else if(s.attachEvent) {
            s.attachEvent('load', function (e) { writeScripts(scripts, callback); });
        }
        var head = document.getElementsByTagName('head')[0];
        head.appendChild(s);
    }
    writeScripts(['george.js','fred.js', 'main.js'], function(){
        var george = new George();
    });
    

    这个脚本像浏览器一样顺序加载,如果你想并行加载,只需循环并添加一个计数变量来处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-18
      • 2013-06-21
      • 2020-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-11
      相关资源
      最近更新 更多