我有一个HTML页面,其中引用了多个JavaScript,CSS和图像文件。这些引用是动态注入的,用户可以手动将HTML页面和支持文件复制到另一台机器上。
如果缺少某些JS或CSS,浏览器会在控制台中抱怨。例如:
错误GET文件:/// E:/SSC_Temp/html_005/temp/Support/jquery.js
我需要以某种方式在HTML页面的内联JavaScript中向我报告这些错误,因此我可以要求用户首先验证是否正确复制了支持文件。
window.onerror
事件只是告诉我页面上有JS错误,例如意外语法错误,但是如果发生错误,则不会触发 404 Not Found 错误。我想在任何资源类型的情况下检查这种情况,包括CSS,JS和图像。
我不喜欢使用jQuery AJAX来验证文件是否物理存在 - 每个页面加载的I / O开销都很昂贵。
错误报告必须包含文件名,因此我可以检查该文件是核心文件还是可选文件。
任何想法?
答案 0 :(得分:44)
要捕获页面上的所有error
个事件,您可以addEventListener
使用useCapture
参数设置为true
。 window.onerror
不会这样做的原因是因为它使用了气泡事件阶段,而您要捕获的error
事件不会冒泡。
如果在加载任何外部内容之前将以下脚本添加到HTML中,则应该能够捕获所有error
事件,即使在离线加载时也是如此。
<script type="text/javascript">
window.addEventListener('error', function(e) {
console.log(e);
}, true);
</script>
您可以通过e.target
访问导致错误的元素。例如,如果您想知道img
标记上没有加载哪个文件,可以使用e.target.src
来获取无法加载的网址。
注意:从技术上讲,它不会检测错误代码,它会检测图像是否无法加载,因为无论状态代码如何,它在技术上都表现相同。根据您的设置,这可能就足够了,但是例如,如果返回带有效图像的404,则不会触发错误事件。
答案 1 :(得分:4)
我将以下代码放在纯JavaScript中,经过测试,并且可以正常运行。 所有源代码(html,css和Javascript)+图像和示例字体都在这里:on github。
第一个代码块是一个对象,其中包含特定文件扩展名的方法:html
和css
。
第二个解释如下,但这里有一个简短的描述。
它执行以下操作:
check_file
有两个参数:一个字符串路径和一个回调函数。ext
)srcFrom
[ext
]对象方法,该方法返回src
,href
等字符串上下文中引用的相对路径数组。为方便起见,它解析为相对路径名,并不关心使用哪种协议(http或https,也没关系)。 它还在解析CSS后清理DOM。
var srcFrom = // object
{
html:function(str)
{
var prs = new DOMParser();
var obj = prs.parseFromString(str, 'text/html');
var rsl = [], nds;
['data', 'href', 'src'].forEach(function(atr)
{
nds = [].slice.call(obj.querySelectorAll('['+atr+']'));
nds.forEach(function(nde)
{ rsl[rsl.length] = nde.getAttribute(atr); });
});
return rsl;
},
css:function(str)
{
var css = document.createElement('style');
var rsl = [], nds, tmp;
css.id = 'cssTest';
css.innerHTML = str;
document.head.appendChild(css);
css = [].slice.call(document.styleSheets);
for (var idx in css)
{
if (css[idx].ownerNode.id == 'cssTest')
{
[].slice.call(css[idx].cssRules).forEach(function(ssn)
{
['src', 'backgroundImage'].forEach(function(pty)
{
if (ssn.style[pty].length > 0)
{
tmp = ssn.style[pty].slice(4, -1);
tmp = tmp.split(window.location.pathname).join('');
tmp = tmp.split(window.location.origin).join('');
tmp = ((tmp[0] == '/') ? tmp.substr(1) : tmp);
rsl[rsl.length] = tmp;
}
});
});
break;
}
}
css = document.getElementById('cssTest');
css.parentNode.removeChild(css);
return rsl;
}
};
这是获取文件内容并根据文件扩展名调用上述对象方法的函数:
function check_file(url, cbf)
{
var xhr = new XMLHttpRequest();
var uri = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function()
{
var ext = url.split('.').pop();
var lst = srcFrom[ext](this.response);
var rsl = [null, null], nds;
var Break = {};
try
{
lst.forEach(function(tgt)
{
uri.open('GET', tgt, false);
uri.send(null);
if (uri.statusText != 'OK')
{
rsl = [uri.statusText, tgt];
throw Break;
}
});
}
catch(e){}
cbf(rsl[0], rsl[1]);
};
xhr.send(null);
}
要使用它,只需将其称为:
var uri = 'htm/stuff.html'; // html example
check_file(uri, function(err, pth)
{
if (err)
{ document.write('Aw Snap! "'+pth+'" is missing !'); }
});
请随意评论和编辑,我这样做很匆忙,所以它可能不那么漂亮:)。
答案 2 :(得分:3)
您可以使用 onload 和 onerror 属性来检测错误
例如,在加载以下html后,它会提供警告 error1 和 error2 ,您可以调用自己的函数,例如onerror(logError(this);)
并将其记录在数组中页面是完全加载的帖子是单个Ajax调用。
<html>
<head>
<script src="file:///SSC_Temp/html_005/temp/Support/jquery.js" onerror="alert('error1');" onload="alert('load');" type="text/javascript" ></script>
</head>
<body>
<script src="file:///SSC_Temp/html_005/temp/Support/jquery.js" onerror="alert('error2');" onload="alert('load');" type="text/javascript" ></script>
</body>
</html>
答案 3 :(得分:0)
您可以将XMLHttpRequest用于文件。
var oReq = new XMLHttpRequest();
oReq.addEventListener("error", transferFailed, false);
function transferFailed(evt) {
alert("An error occurred while transferring the file.");
}
client.open("GET", "unicorn.xml");
client.send();
并使用Image类进行图像处理。
var img1 = new Image();
img1.src = 'http://yourdomain.net/images/onethatdoesnotexist.gif';
img1.onerror = function () { alert( 'Image not loaded' ); };
答案 4 :(得分:0)
@ alexander-omara提供了解决方案。
您甚至可以将其添加到许多文件中,但是可以(应该)添加一次窗口处理程序。
我使用singleton pattern实现了这一点:
some_global_object = {
error: (function(){
var activate = false;
return function(enable){
if(!activate){
activate = true;
window.addEventListener('error', function(e){
// maybe extra code here...
// if(e.target.custom_property)
// ...
}, true);
}
return activate;
};
}());
现在,从任何上下文中调用它都可以,只要一次:
some_global_object.error();