执行通过DOM插入加载的javascript

执行通过DOM插入加载的javascript,javascript,events,dom,asynchronous,Javascript,Events,Dom,Asynchronous,我正在研究一种将小部件添加到客户站点的方法,我希望异步加载我的js,以免阻止客户的页面加载。我已经阅读了很多关于这方面的文章,并且一直在尝试实现这里建议的模式,因为我的项目非常类似: 我遇到的问题是动态加载的javascript文件中的代码无法执行。抱歉,如果这似乎是一个重复的问题,但我花了几个小时搜索和尝试稍微不同的技术,我读了很多帖子,包括这些问题: 但我仍在努力使这项工作,所以我希望如果我直接问这个问题,这里的人可能会帮助我 我目前已经得到了以下作为一个真正的基本测试;很明显,

我正在研究一种将小部件添加到客户站点的方法,我希望异步加载我的js,以免阻止客户的页面加载。我已经阅读了很多关于这方面的文章,并且一直在尝试实现这里建议的模式,因为我的项目非常类似:

我遇到的问题是动态加载的javascript文件中的代码无法执行。抱歉,如果这似乎是一个重复的问题,但我花了几个小时搜索和尝试稍微不同的技术,我读了很多帖子,包括这些问题:

但我仍在努力使这项工作,所以我希望如果我直接问这个问题,这里的人可能会帮助我

我目前已经得到了以下作为一个真正的基本测试;很明显,在我的真实脚本中还有很多事情要做,但我只需要理解这里发生了什么(或者,事实上,什么没有发生)

因此,在我的代码文件“test.js”中,我有:

run_test = function () {
    alert('hello from test');
};
在这一页上,我有:

(function () {
     load_test = function () {
        var t = document.getElementsByTagName('script')[0];
        var s = document.createElement('script');
        s.type = 'text/javscript';
        s.async = true;
        s.src = 'test.js';

        s.onload = s.readystatechange = function () {
            if (run_test) run_test();

            s.onload = null;
            s.onreadystatechange = null;
        };

        t.parentNode.insertBefore(s, t);
    };

    load_test();
})();
我已经在这方面尝试了一些变化——我尝试删除“s.async=true”只是为了看看它是否有区别,但没有。正如我在第一篇文章中提到的,我最初使用的是以下内容,而不是“load_test();”:

window.attachEvent ? window.attachEvent('onload', load_test) : window.addEventListener('load', load_test, false);
但结果总是一样的,我从来没有看到“hello from test”的消息。事实上,我甚至可以在load_test函数中添加警报-如果我在“s.onload=s.readystatechange..”行之前添加警报,我会看到该消息,但该onload函数中的警报永远不会出现。因此,动态添加的脚本的onload似乎永远不会触发

顺便说一句-可能相关也可能无关,但我通常在Firefox中进行测试,如果我在firebug中查看html,我会看到test.js脚本已经加载,但如果我扩展该节点,我只会看到消息“重新加载页面以获取源…”。不管我重新加载页面多少次,我都看不到代码。我曾尝试在其他浏览器中进行测试,结果相同

我忍不住觉得我错过了一些基本的东西;任何帮助都将不胜感激

皮特


谢谢大家的意见

@ZZZBOV,谢谢这个例子,尽管我还不确定自己是否完全理解——我认为“onload”会在脚本加载完成后触发,就像将代码附加到页面的onload事件一样。我对“onreadystatechange”的理解是,它只是为了在IE中捕捉到同样的东西

作为对您的评论的响应,新脚本被插入到页面的头部(带有insertBefore语句),就在原始脚本块的前面(假设原始脚本块位于头部,它就是这样)

关于test.js路径,为了简化示例,我省略了该路径。我的脚本路径绝对正确;我可以通过firebug看到脚本实际上被添加到了(头部)

我的问题是,在加载脚本后,它根本无法运行,但我认为我实际上遇到了一些缓存问题,因为我已经使用我在上面发布的第一个链接中描述的模式实现了这一点(这里也是为了更好的衡量:)

我的代码是这样的:

(function () {
    var addscript = function () {
        var h = document.getElementsByTagName('head')[0],
            s = document.createElement('script');
        s.type = "text/javascript";
        s.async = true;
        s.src = "myscript.js";
        h.appendChild(s);
    };
    window.attachEvent ? window.attachEvent('onload', addscript) : 
        window.addEventListener('load', addscript, false);
})();
如果您查看该帖子上的评论,我认为它在某个地方解释了为什么仍然包含“s.async=true”是一个好主意,即使在这种情况下,脚本附加到窗口onload事件

我的“真正的”主脚本实际上需要jQuery,所以我认为我最终的解决方案是使用类似这样的东西来加载jQuery,然后一旦我知道已经加载了,就让jQuery来加载我需要的任何其他脚本

再次感谢你的帮助


皮特

你的剧本有一些问题。这是一个应该有效的方法

function loadScript(src, callback)
{
  var s, r;
  r = false;
  s = document.createElement('script');
  s.type = 'text/javascript';
  s.src = src;
  s.onload = s.onreadystatechange = function() {
    //console.log( this.readyState ); //uncomment this line to see which ready states are called.
    if ( !r && (!this.readyState || this.readyState == 'complete') )
    {
      r = true;
      callback();
    }
  };
  document.body.appendChild(s);
}
load\u test
函数的问题是,它将在执行新脚本之前调用
run\u test()
。脚本将在第一次
onreadystatechange
事件时删除
onload
onreadystatechange
事件回调,这通常是
加载

另外,
async
应该是不必要的,因为新添加的脚本将插入到
document.body
的末尾。如果要在页面其余部分之后加载脚本,请等待页面其余部分加载(
body.onload
document.onreadystatechange
),然后调用
loadScript


脚本的最大问题听起来像
test.js
在调用它的路径上不存在。确保添加
内联确实有效。

您当然应该用
var
声明“load\u test”。此外,它应该是“onreadystatechange”。另外,我也不确定您是否能在所有浏览器中可靠地获取这些事件。jQuery非常适合跨浏览器规范化事件,这样您就不必这么做了。您好,感谢您的回复@是的,我在load_测试前面添加了“var”,而“readystatechange”只是一个输入错误。我对事件的理解是onreadystatechange适用于IE,onload适用于其他浏览器?这种用法我已经见过很多次了。@zzzzBov,理想情况下,我会对所有内容使用jQuery,但在这种情况下,我会将脚本添加到客户站点,因此无法确定jQuery是否会被引用/加载。