2012-08-13 81 views
15

(先发制人:“为什么我收到此错误:”如果你很想这个标记为重复,注意其他问题似乎问我知道为什么我会出现这个错误;我想知道如何检测我的JavaScript代码中的错误,它只出现在Firebug控制台中,当然,在加载图像时对用户是显而易见的。)检测“图像损坏或截断”在Firefox

I我正在使用picturefill作为响应式图像。我为图像上的加载事件触发了一个回调。因此,每当有人调整浏览器窗口大小时,回调就会运行,以便通过图片填充来加载不同的图像。

回调里面,我的图像数据通过画布转换为dataURL,这样我可以缓存在localStorage的图像数据,以便其提供给即使他们是脱机用户。

备注 “离线” 的部分。这就是为什么我不能依靠浏览器缓存。而HTML5脱机应用程序缓存不符合我的需求,因为图像响应迅速。 (请参阅"Application Cache is a Douchebag"以解释HTML离线应用程序缓存的响应图像的不兼容性。)

在Mac上的Firefox 14.0.1上,如果我调整浏览器的大小然后重新调整大小,则加载图像会触发在大图像有机会完全加载之前再次回到小的位置。它最终会报告Firebug控制台中的“图像损坏或截断”,但不会引发异常或触发错误事件。代码中没有任何迹象表明任何错误。就在Firebug控制台中。同时,它在localStorage中存储截断的图像。

我如何可靠,高效地检测中的JavaScript这个问题,使我不缓存的形象?

这是我遍历picturefill的div如何找到已插入由picturefill 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

+2

难道不是火''元素上的'error'事件? – MaxArt 2012-08-13 06:18:23

+2

有人可能会问,你为什么试图在本地存储中实现自己的图像缓存,而不是让浏览器缓存执行它的工作? – jfriend00 2012-08-13 06:24:54

+0

@ jfriend00我正在缓存图像以供离线使用。我在这个问题上说了这个,但是我把它看成是在旁边。我已经编辑了这个问题,让离线位更加重视。无论如何,下一个明显的问题是为什么不使用HTML5离线应用程序。有关响应式图片与HTML5脱机应用程序缓存不兼容的解释,请参阅http://www.alistapart.com/articles/application-cache-is-a-douchebag/ – Trott 2012-08-13 14:09:08

回答

9

似乎改变img标签的src属性时,火狐触发一个事件load。这是违背了HTML5规范,says如果src属性被改变,那么任何其他已经获取正在进行应该结束(这Firefox没有),任何事件应该被发送。 load事件应该只在抓取成功完成时发送。所以我会说,事实上,你得到一个load事件是一个Firefox的错误。

然而,图像应该知道这是否是完全可用,你可以尝试使用complete属性:

if (this.complete === false) { 
    return; 
} 

不幸的是,Firefox已经this.complete设置为true代替,所以这不是一个选项。

每当您希望更改src属性时,最佳选项可能是创建一个新的<img>元素。

+0

不幸的是,当时的this.complete也是如此,所以没有解决这个问题。我认为一旦.complete被设置为真的,当src被更改时,Firefox从不会将它设置为false Harrumph。感谢您提及HTML5规范,我必须检查一下,我认为这是不明确的,但如果没有,也许是时候提交bug! – Trott 2012-08-17 15:13:42

+0

确实,我现在自己试了一下,'complete'标志仍然是'true',它是只读的,它不能被手动修改回来,所以要么等待Firefox修复这个bug,要么你可以创建一个新的'img'元素,每次你改变'src'并替换旧的' – 2012-08-17 17:35:07

+0

其实,在试用这个例子的时候,我注意到当我改变'src'时没有'load'事件,图像未完全加载在Linux上使用png和jpg图像在FF 14.0.1上测试我创建了[this jsfiddl e](http://jsfiddle.net/GfKCf/5/)来试用它,打开Firebug并观察控制台中记录了哪些事件。 – 2012-08-17 17:50:36

2

今天我就傻眼了这个问题我自己。一切工作正常(图像按预期加载的图像),除了错误不断显示在Firefox错误控制台 - IE或Chrome中没有这样的错误。

在我来说,我是在完整的jQuery处理程序插入的图像与innerHTML的一个div在。当我抢占jquery电话时,错误停止了:

var image_holder = new Image(); 
image_holder.src = img_path;//path of image that's going to be plugged in 

它对我有用,但它仍然没有任何意义。我认为这与时序有关,因为此代码启动要加载的图像,然后才能将代码插入页面。

+0

这也解决了我的问题。奇怪! – 2014-10-09 14:11:27