-1

Per this extremely popular question, preloading images with javascript is as easy as:

function preloadImage(url) {
  var img=new Image();
  img.src=url;
}

But what I'd like to know is how can you know when that's done? I could just do a small setTimeout and assume it will be done after some small delay, but with varying connection speeds and especially for large images or large numbers of images this is unreliable.

Is there any way to actually know for sure when the loading is done?

temporary_user_name
  • 35,956
  • 47
  • 141
  • 220
  • 1
    Does this answer your question? [Preloading images with JavaScript](https://stackoverflow.com/a/38204934/2930038) – vanowm May 12 '22 at 23:51
  • @vanowm did you read the first sentence and second sentence of this question or just jump straight to that? – temporary_user_name May 13 '22 at 00:23
  • The answer in the provided link answers exactly that, so did you read the answers from the "extremely popular question" or just the accepted answer? – vanowm May 13 '22 at 00:38
  • Good point. For the record this exchange could have been avoided if you mentioned more specifically that you were linking to one of the buried answers to that question. Since it's so common on SO to just link to an related but separate question and blow off what someone's actually asking, I assumed that was the case here since your link text is the question's title. – temporary_user_name May 13 '22 at 00:43
  • 1
    Yeah, the comment was automatically generated when I've submitted a link for duplicate topic. and it actually changed my original link to the question rather than the answer...had to manually edit the comment... not very well thought on SO side... – vanowm May 13 '22 at 03:20

2 Answers2

1

Image elements have two events that you can subscribe to to know that the image has loaded: onload and onerror:

function preloadImage(url, doneCallback) {
  var img=new Image();
  img.src=url;

  img.onload = () => {
    doneCallback();
  }

  img.onerror = () => {
    doneCallback(new Error('Failed to load image ' + url));
  }
}

preloadImage(url, (err) => {
  if (err) {
    console.log(err.message);
  }
  else {
    console.log('Preloading DONE!');
    // do what you want after preloading here!
  }
}

Or if you prefer Promises (so you can use async/await etc.):

function preloadImage(url) {
  var img=new Image();
  img.src=url;

  return new Promise((done, fail) => {
    img.onload = () => {
      done();
    }

    img.onerror = () => {
      fail(new Error('Failed to load image ' + url));
    }
  });
}

async function main () {
    console.log('preloading image!');

    await preloadImage(url);

    console.log('done preloading image!');
}

main().catch((err) => {
  console.log(err.message);
});
slebetman
  • 109,858
  • 19
  • 140
  • 171
0

Just found the answer to my own question on the MDN docs for the Image class. There is a complete boolean attribute that tells you whether it's done.

temporary_user_name
  • 35,956
  • 47
  • 141
  • 220
  • This is terrible, terrible idea...you basically making browser hang until image has finished loading... Use `onload` callback – vanowm May 12 '22 at 23:49
  • If you block execution while loading then the loading will **NEVER** complete. This is because the browser's javascript interpreter is single-threaded and will only process network IO at the end of the script. Since your `while` loop never ends the browser will never send the network request to fetch the image – slebetman May 12 '22 at 23:56
  • Good points! Definitely encourage writing an answer with better example usage so I can accept that instead. Meanwhile I at least edited out my bad example. – temporary_user_name May 13 '22 at 00:08