web-dev-qa-db-fra.com

erreur net :: ERR_INSUFFICIENT_RESOURCES lors de l'ajout de nombreux éléments img à dom

J'utilise jquery et backbone.js sur un site qui est assez lourd en image. La fonctionnalité principale du site implique de nombreuses images assez petites (fichiers jpg 150x180px). La liste des images arrive via ajax/json en utilisant une extraction de collection backbone.js. Ensuite, pour chaque modèle de la collection, une vue qui est rendue contient un élément img. La vue est ensuite ajoutée au dom.

Il y a un utilisateur en particulier qui a des milliers d'images - un super cas Edge par rapport au nombre d'images que la plupart de nos utilisateurs normaux ont. Lorsque les données d'image de cet utilisateur se chargent, le navigateur ne peut tout simplement pas gérer le chargement de toutes les images, du moins dans la façon dont notre code actuel fonctionne. Environ la moitié des images se chargent finalement, mais le navigateur (j'utilise chrome 35) ne répond plus pendant plusieurs minutes. L'autre moitié des images ne parvient pas à se charger et la console du navigateur affiche Erreurs "net :: ERR_INSUFFICIENT_RESOURCES" pour les images qui ne se chargent pas.

Voici la partie essentielle de notre code qui charge les images. Quelqu'un peut-il expliquer techniquement pourquoi cet échec de chargement d'image se produit et proposer une solution qui n'implique pas l'ajout de pagination ou la fonctionnalité "cliquez dessus pour charger plus" à la liste d'images?

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

Et le code render () pour la vue App.View.ImageView:

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

Et le modèle utilisé par App.View.ImageView (cela n'est compilé qu'une seule fois en utilisant _.template):

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

Je pense que c'est le bug qui vous affecte: https://bugs.chromium.org/p/chromium/issues/detail?id=108055

Il y a eu des discussions à ce sujet de 2011 à 2016 et se poursuit. Fondamentalement Chrome ne peut pas gérer un très grand nombre de demandes en peu de temps.

Voici ce que aidé un peu pour mon application:

  • Vous pouvez ajouter un gestionnaire d'événements comme img.addEventListener("error",tryAgainLater) mais cela ne sauvera pas les autres ressources qui ne parviennent pas à se charger, de sorte que votre script qui charge des centaines d'images pourrait interférer avec les autres.
  • Essayez de mettre en cache plus d'images pour réduire le nombre de requêtes réseau.
  • Utilisez plutôt Firefox ... ne peut évidemment pas le dire aux clients.

Voici ce que n'a pas fonctionné:

  • Composition des images sur une toile et suppression des images individuelles. Cela n'a pas aidé car il est lié aux requêtes réseau, pas aux images stockées en mémoire.
  • Ne démarre pas la demande suivante tant que l'image précédente n'est pas complètement chargée. C'est peut-être parce qu'il faut du temps pour que la connexion se ferme ou soit supprimée de la mémoire (ou d'une autre ressource).

Encore à essayer:

  • Chargement des images via HTTP/2 ou SPDY où il y a plusieurs demandes mais une seule connexion.
  • Dans votre cas, vous pourriez probablement incorporer les images pour éviter de faire des demandes. Exemple tiré de 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

La méthode toJSON () est très coûteuse pour les navigateurs car elle clone les "attributs" du modèle pour renvoyer une représentation JSON.

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

Dans certains scénarios où je voulais juste afficher les informations de mon modèle, j'ai simplement utilisé directement la propriété 'attributs', cela fait gagner un très bon temps de traitement.

Essayez de remplacer cette ligne dans le fichier ImageView:

theTemplate(this.model.toJSON());

for

theTemplate(this.model.attributes);

J'espère que cette information vous aidera.

4
Gabo