0

I have the following problem. I have a react application that needs to load a grid of individual small, fixed size images, up to a few hundreds (think a 20x20 grid where each cell is a 100x100 image). There is also a combobox where I can choose different selection options, and each option will need to display a different set of images in the matrix.

Right now, what I do is to have a react component that goes through the current prop with the image ids, and creates a <img src> tag with the proper URL. This works, but has a few glitches.

One problem is that the image retrieval, for reasons I won't delve into, is slow and will stay slow. It can take up to a minute to get all the images, and this is expected.

The problem is that with the current arrangement, the following happens:

  1. as soon as the component for the grid is passed a list of image ids, the img tags are added and a set of async requests is spawned for each of the tags. This can take some time to complete, and cannot be interrupted.
  2. when I change the combobox (potentially with the above operation still not completed), the component prop holding the list of ids changes, each <img src> tag is changed by react, this spawns new async retrieval of the new set of images.

The final result is that this not only piles up requests, but also ends up creating a strange situation where the grid displays a mixture of old and new images.

I have control of both the server and the client. Provided that the retrieval of the images will be slow, I am wondering if there are better strategies to:

  1. reduce and control the amount of async requests we perform to retrieve the images, or cancel them, or solve this problem in a different way.
  2. within react, if there's a way to clear the cells when the props change from one list of image ids to the other, so that the cells are emptied and I don't end up with a mixture of old and new images. React sees the change from one list to the other, and generates the new state, but I need to generate an intermediate state where the <img> tags are removed, otherwise the old image remains until the new one is retrieved.
  • Is merging all images in the grid into single one possible on the server side? (i.e. aggregate the query on server side) – wondra Mar 28 '18 at 11:57
  • 1
    @wondra it's technically possible and in fact that was one of the options I considered, but the consequence of it is that of course I would have to use css and background transposing info for each cell. Also, the user would not get anything until the operation is completed. One advantage of the current situation is that, despite its shortcomings, the user starts seeing things happening as each image is loaded. – Stefano Borini Mar 28 '18 at 12:00
1

Some ideas that come to mind (as I do not know all circumstances, there is no definite answer):

  • Aggregate requests: You could send a request for several images in one call. This need not be all 400 cells in one request, but can be smaller blocks, e. g. one row of pictures per request, one column, half a row or column or two rows or columns, or any other block like a 2x2 block, or a 5x10 block or whatever. This would reduce some transfer overhead, at the expense of a more complex processing.
  • As you are in control of the client, you could stop some waste of resources by canceling the requests not necessary any more as the user selected something else. The way I would implement this is giving each request a unique id, and keeping a set of ids for requests sent for which the result was not completely received. Then you can send the list of the obsolete requests with a new request, and the server could abandon these processes. And you client would just have to know to ignore potential error messages for abandoned requests.
1

reduce and control the amount of async requests we perform to retrieve the images, or cancel them, or solve this problem in a different way.

Honestly, this sounds fairly tricky. The only suggestion I have in store adds a layer of complexity, but it might be the only option ...provided your server serves 304 Not Modified for consecutive calls to the same image.

First, I believe that by using <img src="..." />, many browsers will continue loading the image even if you switch out the source. The rationale behind this is that it can be cached afterwards.

Therefore, the only way to go about it, is fetching the images "manually" per XHR, and once the response was completely arrived, insert the link again in the image src which should obtain a 304, hence load it from the browser cache. The big benefit of the XHR is of course that you can abort the request anytime, for instance when you select something else in your combo box.

so that the cells are emptied and I don't end up with a mixture of old and new images.

Well, simply put a step in-between where you fill the grid with placeholder images, like a loading circle ;P

1

I think Medium solves this problem by initializing all images with low res versions of what is about to be displayed. The cached images are prerendered tiny low quality jpg-type blurs that appear almost instantly. More async requests return the full images later.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.