2013-03-24 23 views
14

Tôi có một ứng dụng web tự động tải dữ liệu trong một khoảng thời gian dài. Trong dữ liệu có các liên kết đến hình ảnh được hiển thị trong trình duyệt.Xử lý đúng tài nguyên trình duyệt

ví dụ:

var object = { 
    Name: ko.observable("Foo"), 
    Ref: ko.observable("Bar"), 
    ImageUrl: ko.observable("http://.....")   
} 

Tôi đang sử dụng mẫu Knockoutjs ràng buộc để hiển thị dữ liệu trên màn hình.

<img data-bind="attr: { src: imageUrl }" />   

Vì vậy, mỗi khi đối tượng thay đổi qua cuộc gọi Ajax, mẫu Knockoutjs được hiển thị lại với dữ liệu và hình ảnh thay đổi.

Sau một thời gian dài, những hình ảnh này tích tụ và sẽ ăn nhiều bộ nhớ hơn. Các trình duyệt hiện đại dường như đối phó tốt hơn, nhưng vấn đề là chủ yếu với IE8 (chúng tôi không hỗ trợ < IE8). Ngay cả trong các trình duyệt hiện đại, bộ nhớ cuối cùng sẽ trở nên quá cao khiến trình duyệt bị đóng băng.

Xem ảnh chụp màn hình này để biết ví dụ về tài nguyên hình ảnh đang hình thành.

enter image description here

tôi quyết định để xem những gì sẽ xảy ra nếu thay vì sử dụng một thẻ <img />, sử dụng một <iframe />.

Vì vậy, mã của tôi bây giờ trông giống như

<iframe data-bind="attr: { src: imageUrl }"></iframe> 

gì xảy ra bây giờ là khung được tạo ra, nhưng ngay sau khi những thay đổi imageurl, khung đơn giản là cập nhật và không tạo ra nguồn lực bổ sung.

enter image description here

enter image description here

Vì vậy, nếu tôi muốn giữ lại sử dụng bộ nhớ của trình duyệt xuống, tôi có thể sử dụng kỹ thuật <iframe /> này, nhưng tôi không thích nó. Nó buộc tôi phải thực hiện nhiều thay đổi khác cho ứng dụng, cộng với tôi cần phải sử dụng iframe!

Hiện tại, tôi đã chạy nhiều thử nghiệm khác nhau để xem lượng bộ nhớ được sử dụng bằng cả hai kỹ thuật và trong cùng khoảng thời gian bộ nhớ sẽ tăng từ 81.000k lên 200.000k (với <img />) so với 81,000k đến 98,000k (với <iframe />)

Câu hỏi

có cách nào tốt hơn để quản lý tài nguyên hình ảnh trong một trình duyệt? Có cách nào để xử lý đúng cách hình ảnh này không? Tôi đã tìm kiếm trên web một câu trả lời, nhưng cho đến nay tôi vẫn chưa tìm thấy gì cả.

Sửa

Ở cấp độ rất cơ bản. Tôi đã cố gắng để loại bỏ một hình ảnh thông qua phương pháp jQuery remove(), nhưng tài nguyên hình ảnh không bao giờ được gỡ bỏ. Xem fiddle này cho một ví dụ rất cơ bản.http://jsfiddle.net/ezb9e/

mã:

html

<img src="http://www.fillmurray.com/200/300" /> 

JS

$(function(){ 
    setTimeout(function(){ 
     $('img').remove(); 
     $('body').append($('<img />', { attr: { src: 'http://www.fillmurray.com/300/200' }})); 
    }, 3000);  
}); 
+0

Có thể sử dụng các móc sau: http://knockoutjs.com/documentation/template-binding.html#note_3_using_afterrender_afteradd_and_beforeremove để tự xóa hình ảnh khỏi DOM, trước khi hình ảnh mới được thêm vào? Điều đó sẽ dừng vấn đề. – Nik

+0

Trước tiên tôi đã cố gắng xóa hình ảnh, sau đó thêm hình ảnh mới, nhưng tài nguyên hình ảnh luôn được xây dựng. Xem fiddle này cho một ví dụ. http://jsfiddle.net/ezb9e/ –

+0

Các url hình ảnh luôn thay đổi khi bạn làm mới dữ liệu hay chúng vẫn tương đối ổn định? –

Trả lời

5

tôi sẽ cố gắng sử dụng một tùy chỉnh ràng buộc, và tạo ra và phá hủy các hình ảnh trong đó. Tôi đã có một vấn đề tương tự năm ngoái với một SVG, và đó là những gì tôi phải làm.

ko.bindingHandlers.createImage = { 
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
    // Use something unique to identify this image object 
    var imageName = viewModel.Name(); 
    var parent = bindingContext.$parent; 

    var imageObject = parent.Images[imageName]; 

    if (imageObject) { 
     $(element).empty() 
     imageObject = null; 
    } 

    imageObject = $(element).append('<img src="' + viewModel.imgSrc() + '" />')[0]; 
    parent.Images[imageName] = imageObject; 
    } 
}; 

Dưới đây là tái tạo lại vấn đề ban đầu của bạn:

http://jsfiddle.net/manzanotti/ezb9e/5/

Và đây là phiên bản của tôi:

http://jsfiddle.net/manzanotti/ezb9e/13/

Memory đi lên ban đầu, nhưng nó được thu gom rác tất cả bây giờ và một lần nữa , vì vậy nó không bao giờ bị mất kiểm soát. Điều này được thử nghiệm trong IE9 và Chrome.

Cập nhật Hmmm, tôi không tin rằng điều này hoàn toàn khắc phục sự cố trong IE8. Tôi đã chạy fiddle trong sIEve, và bộ nhớ đang đi lên vẫn còn trong đó, mặc dù như sIEve thêm móc vào các nút DOM, nó có thể là kết quả của việc chạy nó trong sIEve. Chrome chắc chắn là tốt, và IE9 dường như, ít nhất, để được tốt hơn rất nhiều, nếu không hoàn toàn cố định.

+0

Thật không may, có vẻ như IE8 chỉ có một rò rỉ bộ nhớ khá xấu liên quan đến việc tạo ra hình ảnh. Một giải pháp được đề xuất (có vẻ như chỉ hoạt động với một số người), là * bật * "Bật Bộ lọc SmartScreen" trong Tùy chọn Internet nâng cao. Khá phức tạp, nhưng có thể đáng giá nếu bạn thực sự cần sự hỗ trợ của IE8 và không muốn sử dụng iframe. Nguồn: http://com.hemiola.com/2009/11/23/memory-leaks-in-ie8/#comment-880 – snickle