net::ERR_INSUFFICIENT_RESOURCES error when adding numerous img elements to dom

102,223

Solution 1

I believe this is the bug affecting you: https://bugs.chromium.org/p/chromium/issues/detail?id=108055

There's been discussion about it from 2011-2016, and is ongoing. Basically Chrome can't handle a very large number of requests in a short period of time.

Here's what helped a bit for my app:

  • You could add an event handler like img.addEventListener("error",tryAgainLater) but that won't rescue the other resources that fail to load, so your script that loading hundreds of images could interfere with others.
  • Try to cache more of the images to reduce the number of network requests.
  • Use Firefox instead... obviously can't tell customers that.

Here's what did not work:

  • Compositing the images on to a canvas and discarding the individual images. This did not help because it's related to the network requests, not the images stored in memory.
  • Not starting the next request until the previous image is fully loaded. Perhaps this is because it takes time for the connection to actually close or be removed from memory (or some other resource).

Yet to try:

  • Loading the images over HTTP/2 or SPDY where there are many requests but only one connection.
  • In your case you could probably inline the images to avoid making requests. Example from https://css-tricks.com/data-uris/ : <img width="16" height="16" alt="star" src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" />

Solution 2

The method toJSON() is very expensive for the browsers as it clones the 'attributes' in the model to return a JSON representation.

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

In some scenarios where I just wanted to display the information of my model, I simply used the 'attributes' property directly, it saves very good time of processing.

Try replacing this line in the ImageView file:

theTemplate(this.model.toJSON());

for

theTemplate(this.model.attributes);

Hope this information helps.

Share:
102,223
markvicencio
Author by

markvicencio

Updated on July 09, 2022

Comments

  • markvicencio
    markvicencio almost 2 years

    I'm using jquery and backbone.js on a site that is pretty image heavy. The core functionality of the site involves many many fairly small images (150x180px jpg files). The list of images comes in via ajax/json using a backbone.js collection fetch. Then for each model in the collection there is a view that gets rendered which contains an img element. The view is then added to the dom.

    There is one user in particular that has thousands of images - a super edge-case relative to how many images most of our normal users have. When this user's image data loads, the browser just can't handle loading all the images, at least in the way our current code works. About half of the images load okay eventually, but the browser (i'm using chrome 35) becomes unresponsive for several minutes. The other half of the images fail to load, and the browser console shows "net::ERR_INSUFFICIENT_RESOURCES" errors for the images that don't load.

    Here is the essential part of our code that loads the images. Can anyone provide an explanation as to technically why this image loading failure happens, and offer a solution that doesn't involve adding paging or "click her to load more" functionality to the image list?

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

    And the render() code for the App.View.ImageView view:

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

    And the template used by App.View.ImageView (this gets compiled only once using _.template):

    <script type="text/template" id="thumb-template">          
            <a href="<%= ImageUrl%>"><img src="<%= ImageUrl%>" /></a>
            <div class="delete"></div>
    </script>
    
  • Rolf
    Rolf almost 7 years
    Hi, FYI I tried "Loading the images over HTTP/2 where there are many requests but only one connection." but that results in the same problem. My test HTML tries to load 10000 images of 25x25 pixels.
  • Meekohi
    Meekohi about 6 years
    Agreed -- we also tried HTTP/2 and it did not help.