我有一个页面,通过jQuery的$.getScript
函数动态添加脚本引用。脚本加载并执行正常,所以我知道引用是正确的。但是,当我向任何脚本添加“调试器”语句以允许我在调试器(例如VS.Net,Firebug等)中单步执行代码时,它不起作用。似乎jQuery加载脚本的方式阻止了调试器查找文件。
有人为此做了解决方法吗?
答案 0 :(得分:74)
好的,事实证明$.getScript()
函数的默认实现工作方式不同,具体取决于引用的脚本文件是否在同一个域中。外部参考如:
$.getScript("http://www.someothersite.com/script.js")
将导致jQuery创建一个外部脚本引用,可以毫无问题地进行调试。
<script type="text/javascript" src="http://www.someothersite.com/script.js"></script>
但是,如果您引用本地脚本文件,例如以下任何一种:
$.getScript("http://www.mysite.com/script.js")
$.getScript("script.js")
$.getScript("/Scripts/script.js");
然后jQuery将异步下载脚本内容,然后将其添加为内联内容:
<script type="text/javascript">{your script here}</script>
后一种方法 不能与我测试的任何调试器一起工作(Visual Studio.net,Firebug,IE8 Debugger)。
解决方法是覆盖$.getScript()
函数,以便始终创建外部引用而不是内联内容。这是执行此操作的脚本。我已经在Firefox,Opera,Safari和IE 8中对此进行了测试。
<script type="text/javascript">
// Replace the normal jQuery getScript function with one that supports
// debugging and which references the script files as external resources
// rather than inline.
jQuery.extend({
getScript: function(url, callback) {
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = url;
// Handle Script loading
{
var done = false;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function(){
if ( !done && (!this.readyState ||
this.readyState == "loaded" || this.readyState == "complete") ) {
done = true;
if (callback)
callback();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
}
};
}
head.appendChild(script);
// We handle everything using the script element injection
return undefined;
},
});
</script>
答案 1 :(得分:18)
使用JQuery 1.6(可能是1.5),您可以切换到不使用getScript,但使用jQuery.ajax()。然后设置crossDomain:true,你将获得相同的效果。
错误回调无效。所以你不妨把它设置得如下。
但是,我确实设置了一个计时器并成功清除它。所以说10秒后,如果我什么也听不到,我认为文件不好。
jQuery.ajax({
crossDomain: true,
dataType: "script",
url: url,
success: function(){
_success(_slot)
},
error: function(){
_fail(_slot);
}
})
答案 2 :(得分:14)
对于那些想要调试脚本并使用$ .when的人(James Messinger的答案与$ .when不兼容)我建议使用此代码:
var loadScript = function (path) {
var result = $.Deferred(),
script = document.createElement("script");
script.async = "async";
script.type = "text/javascript";
script.src = path;
script.onload = script.onreadystatechange = function (_, isAbort) {
if (!script.readyState || /loaded|complete/.test(script.readyState)) {
if (isAbort)
result.reject();
else
result.resolve();
}
};
script.onerror = function () { result.reject(); };
$("head")[0].appendChild(script);
return result.promise();
};
所有的荣誉和荣耀归于Benjamin Dumke-von der Ehe和他的文章:jQuery script insertion and its consequences for debugging
这适用于$ .when,脚本完全可见且可调试。 感谢。
答案 3 :(得分:2)
试试这个,
jQuery.extend({
getScript: function(url, callback) {
var head = document.getElementsByTagName("head")[0];
var ext = url.replace(/.*\.(\w+)$/, "$1");
if(ext == 'js'){
var script = document.createElement("script");
script.src = url;
script.type = 'text/javascript';
} else if(ext == 'css'){
var script = document.createElement("link");
script.href = url;
script.type = 'text/css';
script.rel = 'stylesheet';
} else {
console.log("Неизветсное расширение подгружаемого скрипта");
return false;
}
// Handle Script loading
{
var done = false;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function(){
if ( !done && (!this.readyState ||
this.readyState == "loaded" || this.readyState == "complete") ) {
done = true;
if (callback)
callback();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
}
};
}
head.appendChild(script);
// We handle everything using the script element injection
return undefined;
}
});
答案 4 :(得分:2)
使用Chrome可以轻松调试它。
1-在要调试的行上写一个console.log(“something”)。
2-观察该日志的控制台。
3-单击日志前面的地址链接。
4-在该行设置断点。
答案 5 :(得分:0)
为避免大量额外编码,您可以试试这个。在您声明$('document').ready()(或调试器将访问的任何其他文件)的文件中,添加类似......
的内容$.debug = function(name) {
var n = name;
}
在调试器的分配行中添加断点。然后,在使用$ .getScript()加载的任何其他js文件中,您可以添加...
$.debug("some string to identify this point of code");
每当执行此行时,调试器将停止并等待您的命令。退出$ .debug函数,就是这样!
答案 6 :(得分:0)
在使用Firebug 2.0.14的Firefox 38.6.0中,当我转到“脚本”选项卡时,我在下拉菜单中看到一个条目,如jquery-1.11.1.js line 338 > eval
,其中包含已加载的脚本。另外,看看这个版本的jQuery中的代码,看起来内部$.getScript()
正在使用$.get()
并最终使用$.ajax()
,唯一的区别是脚本的eval()
部分,由jQuery globalEval()
函数处理:
// Evaluates a script in a global context
// Workarounds based on findings by Jim Driscoll
// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
globalEval: function( data ) {
if ( data && jQuery.trim( data ) ) {
// We use execScript on Internet Explorer
// We use an anonymous function so that context is window
// rather than jQuery in Firefox
( window.execScript || function( data ) {
window[ "eval" ].call( window, data );
} )( data );
}
},
答案 7 :(得分:0)
这将OP解决方案与Eric的解决方案结合在一起。覆盖必要的jquery来处理始终是crossdomain并且它们将完美地显示出来而不会破坏jquery promise实现中的单个事物。
jQuery.extend({
get: function (url, data, callback, type) {
// shift arguments if data argument was omitted
if (jQuery.isFunction(data)) {
type = type || callback;
callback = data;
data = undefined;
}
return jQuery.ajax({
url: url,
type: "GET":,
dataType: type,
data: data,
success: callback,
crossDomain: true
});
}
});
答案 8 :(得分:0)
所有答案都在本页的某个位置,但我想为以后的读者进行总结。
检查(动态添加的)文件下载
使用Chrome,您可以在XHR标签上的网络面板下看到使用$ .getScript(http://api.jquery.com/jQuery.getScript/)添加的Javascript文件;请注意,它们不会出现在“ JS”标签下。
调试文件
1)在代码中设置断点。如其他答案\评论中所述,您可以插入
debugger;
Java代码中的语句。这将调用浏览器的调试器。有关更多信息,请参见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger。
2)使用源地图使其显示在浏览器的“源”面板中(在Chrome中进行测试)。添加
//# sourceURL=whatevername.js
到文件末尾。 [文件显示在Chrome源代码面板中的(无域)下。]
请参阅: How to debug dynamically loaded JavaScript (with jQuery) in the browser's debugger itself?和https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Use_a_source_map了解更多信息。
3)覆盖$ .getScript以始终根据接受的答案使用外部引用(我尚未测试)。