3

On my server, some images take a long time to generate, but then are cached once they are generated, and so subsequent requests are quick.

Currently the server is returning a 202 Accepted HTTP status result when the image is still being generated. It returns a 200 result when the image is already generated can be sent immediately.

To avoid a web-page having a 'broken image' for a long time I have:

  • attached an event handler to the onload event of the image element, that will hide the image and display a placeholder image in its place if the server returned a 202 response.

  • if the image was not loaded with a 200 status start a periodic ajax rqeuest that will periodically check to see if the image is now available, and when it is show the image again.

However this system isn't working properly as I can't see how to tell 200 responses from 202 responses inside the onload event, and so can't tell when the ajax callback needs to be setup.

How can I determine what the status code of the response was that triggered the onload event was?

btw I've considered changed the response code for when the image is still being generated to be one that is considered an error, however the same issue would apply; how to tell the difference between a 'keep trying to load this image' and a genuine server error.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Danack
  • 24,939
  • 16
  • 90
  • 122
  • I'm not using an ajax request so I'm a bit confused by your comment. I'm attached to the document onload/error events i.e. $(this.element).find('.exampleImage').on('load', $.proxy(this, 'imageResult')); When the callback is called e.currentTarget is an HTMLImageElement object, and e.currentTarget.status is undefined. – Danack Sep 09 '15 at 01:37
  • @apsillers Annoyingly, it was doing it like that before.....but I looked at the google page speed analyzer, and it was telling me the page was bad, because the image can't be fully displayed until the javascript is loaded and run. And I strongly dislike having pages that 'flicker' when loaded.....I thought I was being smart to do it this way. – Danack Sep 09 '15 at 01:49
  • Because your periodic check is done with Ajax, I (incorrectly) assumed your initial load was done via Ajax as well. I suspect status information is not made available to element event handlers. Certainly an alternative approach is required here (error status code, or a one-pixel-width image, maybe?) – apsillers Sep 09 '15 at 01:49
  • Grab the image with XHR to get the HTTP status: http://stackoverflow.com/a/17682424/283863 – Derek 朕會功夫 Sep 09 '15 at 02:18

2 Answers2

1

Instead of listening to the onload event, fetch the image with XHR and listen to the onreadystatechange event.

Here's an example: http://jsfiddle.net/DerekL/rwewrrod/

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
    console.log("State: ", this.readyState, "Status: ", this.status);
    if (this.readyState == 4 && this.status == 200) {
        var url = window.URL || window.webkitURL;
        document.querySelector("#img").src = url.createObjectURL(this.response);
    } else if (this.readyState == 4) {
        console.log(this.status);
    } else {
        //not ready yet
    }
}
xhr.open('GET', 'image.png');
xhr.responseType = 'blob';
xhr.send();
Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247
0

It's looking a bit like this might be impossible to do as I originally asked. This is the hack that I'm using to workaround not being able to get the status codes.

  • Change the server to return a status code that indicates an error when the image is still being generated. I choose 420 - 'Enhance your calm'.

  • Make the callback for starting the Ajax asynchronous be listening to the 'onerror' event.

So now, if the image is loaded okay by the browser, no callbacks are called at all, and the image is displayed as soon as possible.

If the initial image request fails, the ajax stuff gets started. Because in the initial onerror callback, we can't tell the difference between actual server errors and the 420 'Image is still being generated' error, this means that there will be duplicate requests when there is an error.....but that is a rare occurrence, and we don't care about having an error delayed by a second.

Danack
  • 24,939
  • 16
  • 90
  • 122