【发布时间】:2013-05-25 08:23:46
【问题描述】:
(先发制人:如果您想将此标记为重复,请注意其他问题似乎在问“我为什么会收到此错误?”我知道为什么会收到此错误;我想知道如何检测我的 JavaScript 代码中的错误。它只出现在 Firebug 控制台中,当然,在加载图像时对用户来说是显而易见的。)
我正在使用picturefill 来获取响应式图像。我有一个为图像上的加载事件触发的回调。因此,每当有人调整浏览器窗口的大小以便通过图片填充加载不同的图像时,回调就会运行。
在回调中,我通过画布将图像数据转换为 dataURL,这样我就可以将图像数据缓存在 localStorage 中,这样即使用户离线也可以使用。
注意关于“离线”的部分。这就是我不能依赖浏览器缓存的原因。而且 HTML5 离线应用程序缓存不能满足我的需求,因为图像是响应式的。 (响应式图片与 HTML 离线应用缓存不兼容的解释见"Application Cache is a Douchebag"。)
在 Mac 上的 Firefox 14.0.1 上,如果我将浏览器的大小调整为非常大的大小,然后在大图像有机会完全加载之前再次将其重新调整为较小的大小,则会触发加载图像。它最终在 Firebug 控制台中报告“图像损坏或截断”,但不会引发异常或触发错误事件。没有迹象表明代码中有任何问题。就在 Firebug 控制台中。同时,它将截断的图像存储在 localStorage 中。
如何在 JavaScript 中可靠有效地检测到此问题,以免缓存该图像?
以下是我如何遍历图片填充 div 以查找图片填充已插入的 img 标签:
var errorLogger = function () {
window.console.log('Error loading image.');
this.removeEventListener('load', cacheImage, false);
};
for( var i = 0, il = ps.length; i < il; i++ ){
if( ps[ i ].getAttribute( "data-picture" ) !== null ){
image = ps[ i ].getElementsByTagName( "img" )[0];
if (image) {
if ((imageSrc = image.getAttribute("src")) !== null) {
if (imageSrc.substr(0,5) !== "data:") {
image.addEventListener("load", cacheImage, false);
image.addEventListener('error', errorLogger, false);
}
}
}
}
}
下面是cacheImage() 回调的样子:
var cacheImage = function () {
var canvas,
ctx,
imageSrc;
imageSrc = this.getAttribute("src");
if ((pf_index.hasOwnProperty('pf_s_' + imageSrc)) ||
(imageSrc.substr(0,5) === "data:") ||
(imageSrc === null) || (imageSrc.length === 0)) {
return;
}
canvas = w.document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.height;
ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
try {
dataUri = canvas.toDataURL();
} catch (e) {
// TODO: Improve error handling here. For now, if canvas.toDataURL()
// throws an exception, don't cache the image and move on.
return;
}
// Do not cache if the resulting cache item will take more than 128Kb.
if (dataUri.length > 131072) {
return;
}
pf_index["pf_s_"+imageSrc] = 1;
try {
localStorage.setItem("pf_s_"+imageSrc, dataUri);
localStorage.setItem("pf_index", JSON.stringify(pf_index));
} catch (e) {
// Caching failed. Remove item from index object so next cached item
// doesn't wrongly indicate this item was successfully cached.
delete pf_index["pf_s_"+imageSrc];
}
};
最后,这里是我在 Firebug 中看到的内容的全文,更改了 URL 以保护有罪者:
图像损坏或截断:http://www.example.com/pf/external/imgs/extralarge.png
【问题讨论】:
-
它不会在
<img>元素上触发error事件吗? -
有人可能会问,为什么您要尝试在本地存储中实现自己的图像缓存,而不是让浏览器缓存来发挥作用?
-
@jfriend00 我正在缓存图像以供离线使用。我在问题中说了这个,但我把它说成是旁白。我已经编辑了这个问题,以更加强调离线。无论如何,下一个明显的问题是为什么不使用 HTML5 离线应用缓存。关于为什么响应式图像和 HTML5 离线应用缓存不兼容的解释,请参阅alistapart.com/articles/application-cache-is-a-douchebag
-
@MaxArt 不,错误事件不会触发。我已编辑问题以包含错误处理程序代码和指示它不会触发的文本。我相信错误事件和加载事件在图像元素上是互斥的。我想 Firefox 选择在加载损坏或截断的图像时触发加载事件。无论如何,这与我所看到的一致。
标签: javascript firefox canvas local-storage picturefill