2014-06-09 11 views
11

Używam jquery i backbone.js na stronie, która jest dość ciężki obraz. Podstawowa funkcjonalność witryny obejmuje wiele bardzo małych obrazów (pliki jpg o wymiarach 150x180px). Lista obrazów jest dostępna za pośrednictwem ajax/json przy użyciu pobierania kolekcji backbone.js. Następnie dla każdego modelu w kolekcji jest wyświetlany widok, który zawiera element img. Widok jest następnie dodawany do dom.net :: ERR_INSUFFICIENT_RESOURCES błąd podczas dodawania wielu elementów img do domena

Jest jeden użytkownik, który ma tysiące zdjęć - bardzo ostry przypadek w stosunku do liczby zdjęć większości naszych zwykłych użytkowników. Gdy ładuje się dane obrazu tego użytkownika, przeglądarka nie radzi sobie z ładowaniem wszystkich obrazów, przynajmniej w taki sposób, w jaki działa nasz obecny kod. Około połowa obrazów ładuje się w porządku, ale przeglądarka (używam chrome 35) przestaje odpowiadać przez kilka minut. Druga połowa obrazów nie ładuje się, a w przeglądarce wyświetlane są błędy "net :: ERR_INSUFFICIENT_RESOURCES" dla obrazów, które nie są ładowane.

Oto niezbędna część naszego kodu, który ładuje obrazy. Czy ktokolwiek może wyjaśnić technicznie przyczyny niepowodzenia ładowania obrazu i zaoferować rozwiązanie , które nie wymaga dodawania stronicowania ani funkcji "kliknij, aby załadować więcej" do listy obrazów?

// inside the view that renders the images 
render: function() { 
    this.collection.each(this.addOne, this);  
    return this; 
}, 
addOne: function (imgModel) { 
    var imgView = new App.Views.ImageView({ model: imgModel}); 
    this.$el.append(imgView.render().el); 
} 

I kod render() dla widoku App.View.ImageView:

render: function() { 
    var renderedTemplate= theTemplate(this.model.toJSON()); 
    this.$el.html(renderedTemplate); 
    return this; 
} 

a szablonu używanego przez App.View.ImageView (to dostaje kompilowane tylko raz przy użyciu _.template) :

<script type="text/template" id="thumb-template">   
     <a href="<%= ImageUrl%>"><img src="<%= ImageUrl%>" /></a> 
     <div class="delete"></div> 
</script> 
+2

Okazało się, że mimo bardzo powolnego ładowania tak wielu obrazów, dziwny błąd pochodzi z AdBlock Plus. Wyłączyłem tę wtyczkę Chrome i błędy zniknęły, a obrazy ładują się dobrze ... po prostu zajmuje to dużo czasu przeglądarce, aby wyrenderować stronę i wykonać całą pracę, którą przeglądarka musi wykonać pod maską. – Rafe

+0

Wiem, że powiedziałeś, że nie chcesz "kliknij tutaj, aby załadować więcej" rozwiązanie, ale mam taką samą sytuację i myślę, że nieskończone przewijanie jest prawdopodobnie najlepszą opcją. Ma to również sens. Po co zmuszać przeglądarkę do renderowania obrazów 8K jednocześnie, gdy tylko ~ 20 z nich będzie widziane przez użytkownika na raz? – djKianoosh

+0

@djKianoosh W moim przypadku obrazy są układane i filtrowane wizualnie za pomocą Isotope. Nie można sortować/filtrować elementów po stronie klienta, które nie są załadowane, dlatego potrzebuję załadować wszystkie elementy. – Rafe

Odpowiedz

3

Sposób toJSON() jest bardzo kosztowne dla przeglądarki, jak Klonów „cechy” w modelu powrotu reprezentację JSON.

... 
// Return a copy of the model's `attributes` object. 
toJSON: function(options) { 
    return _.clone(this.attributes); 
}, 
... 

W niektórych scenariuszach, w których po prostu chciałem, aby wyświetlić informacje o moim modelu, po prostu stosować właściwość „atrybuty” bezpośrednio, zapisuje bardzo dobry czas przetwarzania.

Spróbuj zastąpić ten wiersz w pliku ImageView:

theTemplate(this.model.toJSON()); 

dla

theTemplate(this.model.attributes); 

Nadzieja ta informacja pomaga.

7

Wierzę, że to jest bug wpływ na ciebie: https://bugs.chromium.org/p/chromium/issues/detail?id=108055

Nastąpiła dyskusja o tym od lata 2011-2016 i jest w toku. Zasadniczo Chrome nie może obsłużyć bardzo dużej liczby żądań w krótkim czasie.

Oto co pomógł trochę dla mojej aplikacji:

  • Można dodać obsługi zdarzeń jak img.addEventListener("error",tryAgainLater) ale to nie uratuje innych zasobów, które nie ładować, więc skrypt ładowania setki zdjęć mogą zakłócać działanie innych.
  • Spróbuj buforować większą liczbę obrazów, aby zmniejszyć liczbę żądań sieciowych.
  • Zamiast tego użyj przeglądarki Firefox ... oczywiście nie możesz tego powiedzieć klientom.

Oto co nie działa:

  • złożeniem obrazów na płótnie i odrzucając pojedynczych obrazów. To nie pomogło, ponieważ jest związane z żądaniami sieci, a nie z obrazami przechowywanymi w pamięci.
  • Nie można rozpocząć następnego żądania, dopóki poprzednie zdjęcie nie zostanie w pełni załadowane. Być może dzieje się tak dlatego, że połączenie trwa w rzeczywistości lub jest usunięte z pamięci (lub innego zasobu).

jeszcze spróbować:

  • Ładowanie obrazów za pośrednictwem protokołu HTTP/2 lub SPDY gdzie znajduje się wiele wniosków, ale tylko jedno połączenie.
  • W twoim przypadku możesz prawdopodobnie wstawiać obrazy, aby uniknąć składania próśb. Przykład z: https://css-tricks.com/data-uris/: <img width="16" height="16" alt="star" src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" />
+1

Witam, FYI próbowałem "Ładowanie obrazów przez HTTP/2, gdy jest wiele żądań, ale tylko jedno połączenie." ale to powoduje ten sam problem. Mój testowy HTML próbuje załadować 10000 obrazów o rozmiarze 25x25 pikseli. – Rolf

+0

Zgoda - próbowaliśmy również HTTP/2 i nie pomogło. – Meekohi

Powiązane problemy