2009-07-15 213 views
20

我使用脚本中的位载入另一个:jQuery的getScript()的回调是不可靠的还是我做错了什么?

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

的想法是,$ .getScript加载脚本,那么当它完成执行回调。 CAGInit()是生活在CAGScript.js中的函数。

问题是,大约一半的时间,CAGInit()不会触发(在任何浏览器中)。记录到Firebug控制台报告它没有被定义。剩下的时间它完美的工作。

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

谢谢。

+2

请注意,文档说回调一旦加载脚本就运行,而不一定一旦脚本执行完毕。 – Flimm 2015-06-18 15:30:41

回答

10

如果文件被保存在同一个域,那么jQuery将使用XHR来获取它的内容,然后将在全球范围“EVAL”找到它。这应该很好,但如果你有问题,那么我会建议使用注入脚本标记的替代方法。不幸的是,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); 

这将会是最好摘要的功能;以上只是一个例子...

+0

这一个似乎已经做到了,谢谢:) – 2009-07-15 12:46:46

+3

请注意,这段代码依赖于轮询。这个时间间隔看起来很明智,在很多情况下它可以正常工作,但这绝对不是一个理想的或通用的解决方案。以这种方式进行轮询意味着代码准备就绪以及用户从中获益时几乎总是会出现重大延迟。 – natevw 2011-07-19 18:49:34

+0

@ 999,为什么不需要添加'type'属性呢? – 2012-02-04 13:23:22

0

我想你可以从检查回调函数的testStatus开始,确保脚本真的被加载。回调函数有两个参数,对那些更defails你可以jQuery Docs

$.getScript("CAGScript.js", function (data, textStatus) { 
    if (textStatus === "success") { 
     try { 
      CAGinit(); 
     } catch(err) { 
      console.log(err); 
     } 
    } else { 
     console.log("script not loaded"); 
    } 
}); 
+1

我认为这已经解决了它,但即使在textstatus ===“成功”时,我仍然偶尔会看到“ReferenceError:CAGinit未定义”。我将给予J-P的非XHR解决方案。 – 2009-07-15 12:32:38

9

只是在Firefox上有同样的问题,解决它与一点点黑客。

把它应用到你的例子:

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

基本上迫使XHR响应的评估如果失败本身这样做。

+0

神奇,谢谢。下次我需要加载一个脚本时,我会试一试:) – 2010-01-15 11:55:56

+0

绝妙的想法;为我解决了这个问题:) – thismax 2011-04-29 00:22:19

1

是的,我也发现getScript在FireFox中不可靠,在脚本下载和/或执行之前触发回调。 (使用JQuery 1.41 & 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

22

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

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

jQuery's documentation提到,getScript加入是简写:

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

我已经被这个问题在Chrome得到位:如果我用下面的代替getScript加入

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

一切正常以及。 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的==少的边缘情况= =更少的错误“。通常还有更易读的代码!

20

只是想提供一些我对这个问题的见解。如果您正在加载的代码中存在错误,并且(至少在Chrome上使用jQuery 1.7.1),回调将不会触发,则错误将被吞噬。我发现我在加载的代码中自动完成了一个流浪大括号,并且回调函数没有触发。这里的间歇行为可能是由于测试之间改变加载的代码造成的。

0

我想在JS中实现类似于PHP的auto_load,典型的解决方案是对所有函数使用try-catch ..当函数缺失时,我们跳转到下载它的库.. 我的解决方案取自彼得的解决方案如下:

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

为了确保CAGScript.js被加载并调用CAGinit功能之前执行,最可靠的方法是让内部CAGScript.js函数调用。

CAGScript.js:



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

,然后在你的主文件只需要调用getScript加入():



    $.getScript("CAGScript.js"); 

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

希望这有助于。

0

我的方法是

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

也当我们想更新$范围的数据,它是由在角相同的方式使用$超时解决了我们在棱角分明的脸同样的问题...

相关问题