web-dev-qa-db-ja.com

net :: ERR_INSUFFICIENT_RESOURCESエラーが多数のimg要素をdomに追加するとき

私はかなり画像が重いサイトでjqueryとbackbone.jsを使用しています。サイトのコア機能には、非常に多くの非常に小さな画像(150x180px jpgファイル)が含まれます。画像のリストは、backbone.jsコレクションフェッチを使用してajax/json経由で取得されます。コレクション内の各モデルには、img要素を含むレンダリングされるビューがあります。その後、ビューがdomに追加されます。

特に、数千の画像を持っているユーザーが1人います。これは、通常のユーザーのほとんどが持っている画像の数に比べて、極端なエッジケースです。このユーザーの画像データが読み込まれると、少なくとも現在のコードが機能する方法では、ブラウザはすべての画像の読み込みを処理できません。画像の約半分は最終的には正常にロードされますが、ブラウザ(chrome 35)を使用しています)は数分間応答しなくなります。画像の残りの半分はロードに失敗し、ブラウザコンソールに表示されますロードされないイメージの「net :: ERR_INSUFFICIENT_RESOURCES」エラー。

以下は、画像をロードするコードの重要な部分です。誰もがこの画像の読み込みに失敗する理由を技術的に説明し、解決策を提供できますか?画像ページにページングや「もっと読み込むためにクリックする」機能を追加する必要はありません

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

そして、App.View.ImageViewビューのrender()コード:

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

そして、App.View.ImageViewによって使用されるテンプレート(これは_.templateを使用して一度だけコンパイルされます):

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

これがあなたに影響するバグだと思います: https://bugs.chromium.org/p/chromium/issues/detail?id=108055

2011年から2016年にかけて議論されており、現在も進行中です。基本的にChromeは短時間で非常に多くのリクエストを処理できません。

ここに何があります 少し助けた 私のアプリの場合:

  • img.addEventListener("error",tryAgainLater)のようなイベントハンドラーを追加することはできますが、ロードに失敗した他のリソースをレスキューしないため、数百のイメージをロードするスクリプトが他のリソースに干渉する可能性があります。
  • ネットワーク要求の数を減らすために、より多くの画像をキャッシュしてみてください。
  • 代わりにFirefoxを使用してください。明らかに顧客にそれを伝えることはできません。

ここに何があります 動作しませんでした

  • 画像をキャンバスに合成し、個々の画像を破棄します。これは、メモリに保存されている画像ではなくネットワーク要求に関連しているため、役に立ちませんでした。
  • 前のイメージが完全にロードされるまで、次のリクエストを開始しません。これはおそらく、接続が実際に閉じるか、メモリ(または他のリソース)から削除されるまでに時間がかかるためです。

まだ試してみてください:

  • HTTP/2またはSPDYを介して画像をロードします。リクエストは多くありますが、接続は1つだけです。
  • あなたの場合、おそらくリクエストを行わないように画像をインライン化することができます。 https://css-tricks.com/data-uris/ の例:<img width="16" height="16" alt="star" src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" />
19
WoodenKitty

メソッドtoJSON()は、モデル内の「属性」を複製してJSON表現を返すため、ブラウザーにとって非常に高価です。

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

モデルの情報を表示するだけのシナリオでは、単に「属性」プロパティを直接使用しただけで、非常に良い処理時間を節約できました。

ImageViewファイルの次の行を置き換えてみてください。

theTemplate(this.model.toJSON());

for

theTemplate(this.model.attributes);

この情報がお役に立てば幸いです。

4
Gabo