Recipe 1.2

Loading an Image With a Fallback

Load an image with fallback.

Demo

Valid image
Invalid image, with fallback
Invalid image, no fallback

Code

JavaScript
/**
 * Loads an image. If there's an error loading the image, uses a fallback
 * image URL instead.
 *
 * @param url The image URL to load
 * @param fallbackUrl The fallback image to load if there's an error
 * @returns a Promise that resolves to an Image element to insert into the DOM
 */
function loadImage(url, fallbackUrl) {
  return new Promise((resolve, reject) => {
    const image = new Image();

    // Attempt to load the image from the given URL
    image.src = url;

    // The image triggers the `load` event when it is successfully loaded.
    image.addEventListener('load', () => {
      // The now-loaded image is used to resolve the `Promise`
      resolve(image);
    });

    // If an image failed to load, it triggers the `error` event.
    image.addEventListener('error', error => {
      // Reject the `Promise` in one of two scenarios:
      // (1) There is no fallback URL
      // (2) The fallback URL is the one that failed
      if (!fallbackUrl || image.src === fallbackUrl) {
        reject(error);
      } else {
        // If this is executed, it means the original image failed to load.
        // Try to load the fallback.
        image.src = fallbackUrl; 
      }
    });
  });
}

const validImage = 'https://placekitten.com/g/200/200';
const invalidImage = 'https://example.com/invalid.jpg';

loadImage(validImage).then(image => {
  image.className = 'm-auto';
  document.querySelector('#validImage .card-img-top').appendChild(image);
});

loadImage(invalidImage, validImage).then(image => {
  image.className = 'm-auto';
  document.querySelector('#invalidImageFallback .card-img-top').appendChild(image);
});

loadImage(invalidImage).then(image => {
  image.className = 'm-auto';
  document.querySelector('#invalidImage .card-img-top').appendChild(image);
}).catch(error => {
  const errorImage = new Image();
  errorImage.src = invalidImage;
  document.querySelector('#invalidImage .card-img-top').appendChild(errorImage);
});
HTML
<div class="card-group">
  <div class="card" id="validImage">
    <div class="card-body">
      <h5 class="card-title">Valid image</h5>
      <div class="card-img-top"></div>
    </div>
  </div>

  <div class="card">
    <div class="card-body" id="invalidImageFallback">
      <h5 class="card-title">Invalid image, with fallback</h5>
      <div class="card-img-top"></div>
    </div>
  </div>

  <div class="card">
    <div class="card-body" id="invalidImage">
      <h5 class="card-title">Invalid image, no fallback</h5>
      <div class="card-img-top"></div>
    </div>
  </div>
</div>
Web API Cookbook
Joe Attardi