2012-08-13 12 views
15

(Cảnh cáo ưu tiên: Nếu bạn bị cám dỗ đánh dấu mục này là trùng lặp, hãy lưu ý rằng các câu hỏi khác dường như hỏi "tại sao tôi gặp lỗi này?" 'm nhận được lỗi này; Tôi muốn biết làm thế nào tôi có thể phát hiện lỗi trong mã JavaScript của tôi. Nó chỉ xuất hiện trong giao diện điều khiển Firebug và, tất nhiên, hiển nhiên đối với người dùng khi hình ảnh được tải.)Phát hiện "hình ảnh bị hỏng hoặc cắt ngắn" trong Firefox

I đang sử dụng picturefill cho hình ảnh phản hồi. Tôi có một cuộc gọi lại được kích hoạt cho sự kiện tải trên hình ảnh. Vì vậy, cuộc gọi lại chạy mỗi lần ai đó thay đổi kích thước cửa sổ trình duyệt sao cho một hình ảnh khác được tải qua hình ảnh.

Bên trong hàm gọi lại, tôi đang chuyển đổi dữ liệu hình ảnh thành dataURL qua canvas để tôi có thể lưu trữ dữ liệu hình ảnh trong localStorage để có sẵn cho người dùng ngay cả khi họ ngoại tuyến.

Lưu ý một phần về "ngoại tuyến". Đó là lý do tại sao tôi không thể dựa vào bộ nhớ cache của trình duyệt. Và bộ nhớ cache ứng dụng ngoại tuyến HTML5 không đáp ứng nhu cầu của tôi vì hình ảnh phản hồi. (Xem "Application Cache is a Douchebag" để giải thích về sự không tương thích của hình ảnh phản hồi với bộ nhớ cache ứng dụng ngoại tuyến HTML.)

Trên Firefox 14.0.1 trên máy Mac, hình ảnh tải sẽ kích hoạt nếu tôi thay đổi kích thước trình duyệt thành thứ gì đó thực sự lớn và sau đó thay đổi kích thước quay trở lại một cái gì đó nhỏ một lần nữa trước khi hình ảnh lớn có một cơ hội để tải đầy đủ. Nó kết thúc báo cáo "Hình ảnh bị hỏng hoặc cắt ngắn" trong bảng điều khiển Firebug, nhưng không ném ngoại lệ hoặc kích hoạt sự kiện lỗi. Không có dấu hiệu gì sai trong mã. Chỉ trong giao diện điều khiển Firebug. Trong khi đó, nó lưu trữ một hình ảnh cắt ngắn trong localStorage.

Làm cách nào để phát hiện sự cố này một cách đáng tin cậy và hiệu quả trong JavaScript để tôi không lưu hình ảnh đó?

Đây là cách tôi lặp qua các divs picturefill để tìm thẻ img đã được chèn vào bởi picturefill:

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); 
        } 
       } 
      } 
     } 
    } 

Và đây là những gì các cacheImage() callback trông giống như:

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]; 
    } 
}; 

Cuối cùng, đây là nội dung đầy đủ về những gì tôi thấy trong Firebug với URL đã thay đổi để bảo vệ sự phạm tội:

ảnh bị hỏng hoặc cắt ngắn: http://www.example.com/pf/external/imgs/extralarge.png

+2

Nó không kích hoạt sự kiện 'lỗi' trên phần tử' '? – MaxArt

+2

Bạn có thể hỏi tại sao bạn đang cố gắng triển khai bộ nhớ đệm hình ảnh của riêng mình trong bộ nhớ cục bộ thay vì chỉ để bộ nhớ cache của trình duyệt hoạt động? – jfriend00

+0

@ jfriend00 Tôi đang lưu vào bộ nhớ cache hình ảnh để sử dụng ngoại tuyến. Tôi nói điều này trong câu hỏi, nhưng tôi đã nói nó như một bên. Tôi đã chỉnh sửa các câu hỏi để cung cấp cho các bit ẩn sự chú ý hơn. Dù sao thì, câu hỏi hiển nhiên tiếp theo là tại sao không sử dụng ứng dụng HTML5 offline appcaching. Để giải thích lý do tại sao hình ảnh phản hồi và HTML5 appcaching không tương thích, hãy xem http://www.alistapart.com/articles/application-cache-is-a-douchebag/ – Trott

Trả lời

9

Dường như khi thay đổi src thuộc tính của thẻ img, Firefox bắn một sự kiện load. Điều này trái ngược với đặc tả HTML5, trong đó says rằng nếu thuộc tính src bị thay đổi, thì mọi tiến trình tìm nạp khác đã được tiến hành phải được kết thúc (Firefox nào) và không có sự kiện nào được gửi đi. Sự kiện load chỉ được gửi nếu quá trình tìm nạp được hoàn tất thành công. Vì vậy, tôi muốn nói rằng thực tế là bạn nhận được sự kiện load là lỗi của Firefox.

Tuy nhiên, hình ảnh nên biết nếu nó là hoàn toàn có sẵn hay không, bạn có thể thử sử dụng complete thuộc tính:

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

Thật không may, trình duyệt Firefox có this.complete thiết lập để true thay thế, do đó không phải là một tùy chọn.

Tùy chọn tốt nhất có thể là tạo phần tử <img> mới mỗi khi bạn muốn thay đổi thuộc tính src.

+0

Thật không may, this.complete cũng đúng vào thời điểm đó, vì vậy điều đó không xảy ra xung quanh vấn đề. Đúng vậy, Firefox không bao giờ đặt nó thành false khi src bị thay đổi. Harrumph Cám ơn vì đã nhắc đến spec HTML5 Tôi sẽ phải kiểm tra điều đó.Tôi nghĩ nó không rõ ràng về điều này, nhưng nếu không, có lẽ đã đến lúc nộp – Trott

+0

Thật vậy, tôi đã thử nó ngay bây giờ và cờ 'complete' vẫn là' true', và nó chỉ đọc, nó không thể được thay đổi theo cách thủ công. Vì vậy, hãy chờ Firefox sửa lỗi này hoặc bạn có thể tạo một phần tử 'img' mới mỗi khi bạn thay đổi' src' và thay thế phần tử cũ. –

+0

Thực ra, trong khi thử ví dụ, tôi nhận thấy rằng tôi không nhận được sự kiện 'load' khi thay đổi' src' và thử nghiệm trên FF 14.0.1 trên Linux, sử dụng cả hình ảnh png và jpg. Tôi đã tạo [jsfiddl này e] (http://jsfiddle.net/GfKCf/5/) để dùng thử, mở Firebug và xem các sự kiện nào được ghi trong bảng điều khiển. –

2

Tôi đã bị sững sờ bởi vấn đề này ngày nay. Mọi thứ đều hoạt động tốt (các hình ảnh được tải trực quan như mong đợi) ngoại trừ lỗi được hiển thị trong bảng điều khiển lỗi của Firefox - không có lỗi nào trong IE hoặc Chrome.

Trong trường hợp của tôi, tôi đã cắm một hình ảnh vào một div với innerHtml trong một trình xử lý jquery hoàn chỉnh. Các lỗi dừng lại khi tôi đã chặn trước cuộc gọi jquery với:

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

Nó làm việc cho tôi, nhưng nó vẫn không có ý nghĩa. Tôi giả sử nó là một cái gì đó để làm với thời gian như mã này bắt đầu hình ảnh để tải trước khi nó được vào mã mà thực sự cắm nó vào trang.

+0

Điều này cũng đã sửa nó cho tôi. Lạ thật! –