jQuery的getScript()上的回调是不可靠的还是我做错了什么?

时间:2009-07-15 11:46:59

标签: javascript jquery

我正在使用以下脚本来加载另一个脚本:

$.getScript("CAGScript.js", function () {
    try {
        CAGinit();
    } catch(err) {
        console.log(err);
    }
});

这个想法是$ .getScript加载脚本,然后在完成后执行回调。 CAGInit()是一个位于CAGScript.js的函数。

问题是大约有一半的时间,CAGInit()不会触发(在任何浏览器中)。登录到Firebug控制台会报告它未定义。其余时间它完美运作。

有没有人有任何想法我做错了什么?

感谢。

11 个答案:

答案 0 :(得分:23)

我注意到FF 3.6也存在同样的问题。

解决方案是同步加载脚本。

jQuery's documentation中所述,getScript是:

的简写
$.ajax({
  url: url,
  dataType: 'script',
  success: success
});

如果我使用以下代码而不是getScript,那么一切正常:

$.ajax({
  url: url,
  dataType: 'script',
  success: success,
  async: false
});

答案 1 :(得分:20)

我想就此问题提供一些见解。如果您正在加载的代码中出现错误,并且(至少在使用jQuery 1.7.1的Chrome上)错误将被吞没,则不会触发回调。我发现在我加载的代码中有一个来自自动完成的杂散花括号,并且回调函数没有触发。这里的间歇性行为可能是由测试之间更改加载的代码引起的。

答案 2 :(得分:10)

如果文件保存在同一个域中,那么jQuery将使用XHR检索其内容,然后全局“评估”它。这应该工作正常,但如果你遇到问题,那么我建议使用注入脚本标记的替代方法。不幸的是,jQuery没有公开这个功能所以你必须自己做:

var script = jQuery('<script/>').attr('src', 'CAGSCript.js').appendTo('head');

var timer = setInterval( function(){ 
    if (window.CAGInit !== undefined) {
        clearInterval(timer);
        script.remove();
        // Do your stuff:
        CAGInit();
    }
}, 200);

最好把它抽象成一个函数;以上只是一个例子...

答案 3 :(得分:9)

在firefox上遇到同样的问题,用一点点黑客解决了它。

将它应用于您的示例:

$.getScript("CAGScript.js", function (xhr) {
    try {
        CAGinit();
    } catch(err) {
        eval(xhr);
        CAGinit();
    }
});

基本上强制评估XHR响应,如果它本身不能这样做。

答案 4 :(得分:3)

我也在Chrome上遇到过这个问题。 jQuery偶尔会调用成功回调,好像一切都好,但脚本实际上并没有正确加载。在我们的例子中,解决方案是简单地从信任jQuery改变:

<script>
    $.getScript("helpers.js", function () {
        // use helpers....or: EXPLODE (wheeeee!)
        helpers.doSomething();
    });
</script>

信任浏览器:

<script src="helpers.js"></script>
<script>
    helpers.doSomething();
</script>

我一次又一次地发现“jQuery == less edge = = less bugs”。通常也是更易读的代码!

答案 5 :(得分:3)

为了确保在调用CAGinit函数之前CADScript.js是LOADED和EXECUTED,最可靠的方法是在CAGScript.js中调用函数。

CAGScript.js:



    ...
    /*
    your code
    */
    function CAGinit(){
    ...
    }
    ...
    /* last line */
    CAGinit();

然后,在主文件中调用getScript():

 

    $.getScript("CAGScript.js");

答案 6 :(得分:1)

是的,我也发现在FireFox中getScript不可靠,在脚本下载和/或执行之前触发了回调。 (使用JQuery 1.41&amp; FireFox 3.6。问题似乎并不影响IE,Chrome或Opera。)

我还没有进行过广泛的测试,但似乎只发生了一些特定的脚本......不确定原因。

RaYell的建议不起作用,因为即使脚本尚未被评估,getScript也会报告成功。在大多数情况下,Pieter的建议导致代码被评估两次,效率低下并且可能导致错误。

这个替代方案似乎适用于getScript没有的地方。请注意,它似乎是添加了一个SCRIPT DOM元素,而getScript则添加了XHR。

http://www.diveintojavascript.com/projects/sidjs-load-javascript-and-stylesheets-on-demand

答案 7 :(得分:0)

我认为你可以从检查回调函数的testStatus开始,以确保脚本真正加载。回调函数有两个参数,对jQuery Docs

上可以找到的参数更加失败
$.getScript("CAGScript.js", function (data, textStatus) {
    if (textStatus === "success") {
        try {
            CAGinit();
        } catch(err) {
            console.log(err);
        }
    } else {
        console.log("script not loaded");
    }
});

答案 8 :(得分:0)

我希望在JS中使用PHP实现与auto_load类似的东西,典型的解决方案是在所有函数上使用try-catch ..当函数丢失时,我们跳转到下载它的库.. 我的解决方案来自Pieter解决方案如下:

function CheckUserPW(username,password){
    try{
       loginCheckUserPW(username,password);
    } catch(err) {
        $.getScript('login.js', function(xhr){ 
            eval(xhr);
            loginCheckUserPW(username,password);
        });
    }
}

答案 9 :(得分:0)

似乎jQuery现在处理跨域和相同的域请求就好了。对于跨域请求,它将添加脚本标记并订阅错误和加载事件并适当调用完成和错误回调,只有在请求失败时才会出错,评估脚本的错误仍将被视为成功就请求而言。对于同源,它将执行XHR请求然后执行globalEval,一旦完成,调用完成的回调,如果在此过程中任何失败,它将调用您的错误回调。

使用XHR有一些问题,它打破了调试器,源映射,它依赖于globalEval,它与ContentSecurityPolicy有问题。为了保持一致性,我们只需在加载脚本时添加脚本标记。

var scriptElement = $("<script>").prop({src: url, async: true}); scriptElement.one('load', ()=> ...); scriptElement.one('error', (evt)=> ...); document.head.appendChild(scriptElement[0]);

如果你想在没有jQuery搜索的情况下进行动态导入this article

中的脚本

希望这会有所帮助。

答案 10 :(得分:0)

我的方式是

setTimeout(function(){ 
  $.getScript( "CAGScript.js");
  }, 
2000);

当我们想要更新$ scope中的数据时,我们面对角度也是同样的问题,并且通过在角度中以相同的方式使用$ timeout来解决...